Back to skill

Security audit

ScholarGraph

Security checks for vulnerabilities and agentic risk

Overview

ScholarGraph is a coherent academic literature tool, but it has serious implementation risks that could expose API keys or execute code through crafted files, paths, or generated HTML.

Install only after review or in an isolated environment. Avoid using the PDF figure extraction and PPT export features on untrusted paths or files, avoid opening or hosting generated HTML from untrusted paper metadata, do not run config show/init where API keys may be logged or saved, and pin dependencies before using it with sensitive research or credentials.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (7)

T09 · Insecure Skill Coding Practices

Error
Location
paper-viz/scripts/ppt-exporter.ts:70
Finding

Arbitrary Python Code Execution Through PPT Output Path Injection

Content
View full analysis
{ return this.runCommand(this.pythonPath, ['-c', code]); } ``` The CLI supplies the path: ```ts const outputIndex = args.indexOf('--output'); const outputFile = outputIndex > -1 ? args[outputIndex + 1] : undefined; const exportPpt = args.includes('--ppt'); const htmlPath = outputFile || `${analysis.metadata.title.slice(0, 50).replace(/[^\w\s-]/g, '').trim().replace(/\s+/g, '-')}-viz.html`; if (exportPpt) { const pptPath = htmlPath.replace(/\.html$/, '.pptx'); const exporter = new PptExporter(); await exporter.export(presentation, { outputPath: pptPath }); } ``` ### Technical Analysis Replacing backslashes does not make a string safe for interpolation into Python source. A path containing a double quote, newline, or other Python syntax can terminate the string literal and append attacker-controlled statements. The child process is created without a shell, but that does not prevent this vulnerability because the injection occurs inside the Python program passed to `python - ...[truncated 1082 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
paper-viz/scripts/pdf-figure-extractor.ts:138
Finding

Arbitrary Python Code Execution Through PDF and Figure Output Paths

Content
View full analysis
{ return this.runCommand(this.options.pythonPath, ['-c', code]); } ``` ### Technical Analysis A filename is data, but this implementation treats it as part of executable Python source. Backslash normalization does not escape double quotes, newlines, or Python syntax. Consequently, a malicious `pdfPath` or configured `outputDir` can break out of the assigned string and add arbitrary statements to the generated program. This flaw affects direct API consumers of `PdfFigureExtractor`. It can also become remotely reachable when an integrating application derives local PDF paths from untrusted metadata. ### Attack Path 1. An attacker supplies or causes the application to use a PDF filename or output directory containing Python string-termination characters and injected statements. 2. `extract()` confirms that the attacker-selected path exists. 3. `build ...[truncated 565 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
graph-viz/scripts/html-generator.ts:85
Finding

Stored Script Injection in Generated Knowledge-Graph HTML

Content
View full analysis
<\/script> ` is interpreted by the HTML parser as the end of the script element even when it appears inside a JavaScript string. Academic titles, abstracts, graph labels, descriptions, author names, and paper payload fields can originate from external services or AI output. A value such as a closing script tag followed by a new script element can therefore terminate the serialized data block and inject executable JavaScript. This is a stored injection issue because the payload is persisted in the generated HTML and executes later when a user opens the visualization. ### Attack Path 1. An attacker controls or poisons paper metadata, graph content, or an upstream API/AI response. 2. The malicious value is stored in `data.nodes`, `data.edges`, or `paperPayload`. 3. `generateGraphHtml()` serializes the value using plain `JSON.stringify()`. 4. The generated HTML contains an attacker-supplied closing script sequence. 5. When a researcher opens the graph file, the browser terminates the intended script block and executes the injected script. ### Impact Assessment The injected script executes in the generated document's origin. Depending on how the file is hosted or opened, it can modify the visualization, present phishing interfaces, read document-accessible data and localStorage, ini ...[truncated 222 chars]
Remediation
View remediation
`, `&`, U+2028, and U+2029 after JSON serialization. - A typical minimum transformation is: ```ts function serializeForInlineScript(value: unknown): string { return JSON.stringify(value) .replace(//g, '\\u003e') .replace(/&/g, '\\u0026') .replace(/\u2028/g, '\\u2028') .replace(/\u2029/g, '\\u2029'); } ``` - Prefer embedding JSON in a non-executable data element and reading its `textContent`, while still preventing premature element termination. - Add a restrictive Content Security Policy. Avoid allowing unrestricted inline scripts where practical. - Add regression tests using closing script tags in every externally derived text field. - Consider bundling a pinned D3 asset locally instead of loading executable JavaScript from a CDN at report-view time. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
graph-viz/scripts/html-generator.ts:590
Finding

Dangerous URL Schemes Allowed in Generated Graph Links

Content
View full analysis
Open Paper'; } ``` The same pattern is used in paper-preview HTML: ```js (paper.url ? '' : '') ``` The escaping helper only performs HTML-character escaping: ```js function escHtml(s) { if (!s) return ''; return s.replace(/&/g,'&').replace(//g,'>').replace(/"/g,'"'); } ``` ### Technical Analysis HTML escaping prevents attribute-boundary injection but does not validate the URL scheme. An attacker-controlled paper URL can use a dangerous scheme such as `javascript:` or an inappropriate `data:` URL. When the user clicks the generated link, the browser may execute attacker-controlled content. The links also use `target="_blank"` without `rel="noopener noreferrer"`, which can expose the opener window to navigation or manipulation by an untrusted destination in affected environments. ### Attack Path 1. A malicious or compromised academic data source supplies a crafted paper URL. 2. ScholarGraph places the URL into `paperPayload`. 3. The graph generator HTML-escapes the value but does not enforce an allowed protocol. 4. A researcher opens the visualization and clicks “Open Paper” or “View Paper.” 5. The browser processes the attacker-selected URL scheme or opens an untrusted page with opener access. ### Impact Assessment Exploitation requires user interaction but can result in script execution in a generated preview context, phishing, forced navigation, or access to opener-window functions. The exact scope depends on browser behavior and whether the generated visualization is opened locally or hosted under an ap ...[truncated 21 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
config.ts:190
Finding

API Credentials Persisted in Plaintext and Printed to Standard Output

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
paper-viz/scripts/pdf-figure-extractor.ts:65
Finding

Automatic Installation of Unpinned Python Packages During Feature Execution

Content
View full analysis
{ try { const result = await this.runCommand(this.options.pythonPath, [ '-m', 'pip', 'install', 'pymupdf', '--quiet', ]); return result.exitCode === 0; } catch { return false; } } ``` It is triggered during normal extraction: ```ts if (!available) { console.log('pymupdf not found, attempting to install...'); const installed = await this.installPymupdf(); if (!installed) { console.error('Failed to install pymupdf. Please run: pip install pymupdf'); return []; } } ``` PPT export behaves similarly: ```ts async installPptx(): Promise { try { const result = await this.runCommand(this.pythonPath, [ '-m', 'pip', 'install', 'python-pptx', '--quiet', ]); return result.exitCode === 0; } catch { return false; } } ``` ```ts if (!available) { console.log('python-pptx not found, attempting to install...'); const installed = await this.installPptx(); if (!installed) { throw new Error('Failed to install python-pptx. Please run: pip install python-pptx'); } } ``` ### Technical Analysis Normal feature invocation silently modifies the active Python environment and retrieves the latest package release available from pip's configured index. No version or hash is pinned. Python package installation may execute build backends and installation hooks, so the effective code introduced into the environment can change after the Skill itself has been audited. The selected package index can also be changed by local pip configuration or environment variables, increasing the risk of obtaining packages from an untrusted source. ### Attack Pat ...[truncated 754 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
package.json:36
Finding

Production Dependency Uses an Unpinned Latest Version

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (130)

Tp4

High
Category
MCP Tool Poisoning
Confidence
87% confidence
Finding

The declared description emphasizes an academic literature intelligence toolkit focused on multi-source paper search, analysis, and knowledge graph building. The supplied code instead primarily implements a concept-learning assistant: it uses an AI provider to generate structured concept summaries, histories, applications, related concepts, learning paths, comparisons, and optional code examples. It does include a limited paper-fetching feature via Semantic Scholar with web-search fallback, but this is ancillary rather than the main purpose. There is no evidence of knowledge graph construction, multi-source scholarly aggregation beyond one API plus generic web search, or broader literature-analysis workflows. Therefore the implementation materially differs from the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The declared description emphasizes an academic literature intelligence toolkit focused on searching papers across sources, analyzing literature, and building knowledge graphs. The supplied code chunk does not implement any such functionality; it is purely a set of static type definitions for a 'Concept Learner' model. While some interfaces reference papers and related concepts, these are just schema definitions and do not perform search, analysis, graph construction, or AI assistance. This is a material purpose mismatch rather than a supporting internal detail.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description emphasizes literature intelligence functions such as multi-source paper search, analysis, knowledge graph construction, and AI assistance. The supplied code does not implement search, analysis, knowledge graph features, or AI behaviors. Instead, it is a presentation HTML generator for rendering paper summaries/slides with styling and client-side interactivity. It also introduces undeclared browser-side editing and localStorage persistence capabilities. This is a materially different primary purpose rather than a minor supporting component of the declared toolkit, so the description does not accurately represent this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description emphasizes academic paper search, analysis, and knowledge graph building. This code instead performs document export: it generates PowerPoint presentations from presentation data by spawning Python, checking for/installing python-pptx, writing temp files, and saving a .pptx file. Those are materially different capabilities from literature intelligence and are not clearly represented in the declared purpose. The subprocess execution and package installation are especially notable undeclared behaviors.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The declared description emphasizes a research intelligence toolkit with multi-source paper search, analysis, knowledge graph building, and AI assistance. The supplied code chunk does not implement any of those capabilities. Instead, it provides static type definitions and theme constants for representing academic presentation slides, figures, themes, and PPT export settings. This indicates a materially different primary purpose: presentation generation/visualization for papers rather than literature intelligence or knowledge graph tooling.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The code is clearly focused on tracking new literature updates for configured watches (keywords, authors, conferences), collecting results mainly from Semantic Scholar with optional web search fallback, then generating summaries, recommendations, trend snapshots, and Markdown reports. This partially overlaps with academic literature search/analysis and AI assistance, but an important declared capability—knowledge graph building—is absent. The described 'multi-source paper search' is also overstated relative to the implementation, which uses one academic API plus optional web search rather than a broader source integration layer. Additionally, the module’s main behavior is ongoing monitoring/reporting rather than a general-purpose literature intelligence toolkit. Therefore the description does not accurately represent the supplied code chunk.

Content

No source excerpt is available for this finding.

Ssd 1

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

Untrusted paper text is interpolated directly into the user prompt sent to the model, allowing embedded prompt-injection instructions inside the paper content to steer the model away from the intended analysis task. In this skill, the model's output is then trusted as structured analysis, so adversarial text in a paper or fetched snippet can manipulate conclusions, fabricate metadata, or induce downstream unsafe behavior in consumers of the analysis.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The documentation is written entirely in Chinese and even the sample configuration sets primaryLanguage to zh-CN, but the README does not state that this is region-specific or offer an alternate language option. Under SQP-3, forcing a specific language or locale without user opt-in is a policy concern.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README instructs users to configure multiple third-party AI and search providers but does not clearly warn that prompts, search queries, paper URLs, abstracts, and possibly document-derived content may be transmitted to those external services. In a literature-analysis tool, users may submit unpublished research ideas, sensitive topics, or proprietary documents, so missing privacy disclosure can lead to unintended data exposure.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · SKILL.md (reported line 303)May include surrounding context.

From specific URL

lit review-graph "https://arxiv.org/abs/xxxx" --output my-graph --enrich

Auto-confirm mode (non-interactive)

lit review-graph "transformer" --output tf-graph --enrich --auto-confirm

text

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · SKILL.md (reported line 304)May include surrounding context.

lit review-graph "https://arxiv.org/abs/xxxx" --output my-graph --enrich

Auto-confirm mode (non-interactive)

lit review-graph "transformer" --output tf-graph --enrich --auto-confirm

text

### Query Knowledge Graph

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code file contains extensive user-facing help text and command descriptions in Chinese, and the runtime output throughout the CLI also uses Chinese labels. Because the skill does not offer any language/locale selection or explain that it is intentionally China/Chinese-region specific, it violates the language-choice policy for natural-language behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The code sends paper title, keywords, abstract, key points, and contributions to an external AI provider with no visible consent gate, minimization, or warning in this file. In an academic research workflow, those fields may contain unpublished, licensed, or otherwise sensitive material, so silent transmission creates a real confidentiality and compliance risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The natural-language prompts and system instruction are written to require Chinese output such as Chinese field descriptions and '你是学术概念提取专家', with no indication of user opt-in or configurable locale. This appears to enforce a specific language behavior rather than offering a language or locale choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The relation extraction step uses Chinese-only instructions and a Chinese system prompt, which imposes a specific language/locale behavior. The file does not show any mechanism for user choice or any documented rationale for restricting the skill to Chinese-language operation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The default language is hard-coded to zh-CN, and prompt construction then forces either Chinese or English responses based on that setting. This creates a language-policy issue because users are defaulted into a specific locale without being asked or offered a neutral default.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

User-supplied concept strings are transmitted to external AI providers and, depending on options, to external search services without an explicit privacy warning at the point of use. If users enter proprietary research topics, internal project names, or sensitive study areas, this can cause unintended disclosure to third parties.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
88% confidence
Finding

The code sends user-provided concept queries to Semantic Scholar over the network, which is an external data transmission. In an academic assistant this is expected, but it still creates a real privacy boundary: sensitive or proprietary concepts may be exposed to third-party services and logs.

Content

Scanner excerpt · concept-learner/scripts/learn.ts (reported line 189)May include surrounding context.

ts
private async searchSemanticScholar(concept: string): Promise<Paper[]> {
    try {
      const fields = 'paperId,title,abstract,authors,year,citationCount,venue,url';
      const url = `https://api.semanticscholar.org/graph/v1/paper/search?query=${encodeURIComponent(concept)}&limit=5&fields=${fields}`;

      const response = await fetch(url);
      if (!response.ok) {

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The overview is written entirely in Chinese and presents the skill as operating in that language by default, without stating that users can choose another language or that the skill is region-specific. Under the policy, forcing a specific language without user opt-in is a natural-language locale violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The default primaryLanguage is set to zh-CN, which imposes a specific locale unless the user explicitly changes it. This matches the policy category for language or locale constraints without opt-in, especially since the config schema supports multiple languages.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The help text claims support for variables such as OPENAI_API_KEY, ANTHROPIC_API_KEY, AZURE_OPENAI_ENDPOINT, OLLAMA_BASE_URL, QWEN_API_KEY, DASHSCOPE_API_KEY, QWEN_BASE_URL, QWEN_MODEL, and SERPER_API_KEY. However, the implemented defaults in this file only read AI_PROVIDER, AI_API_KEY, AI_BASE_URL, AI_MODEL, NCBI_API_KEY, IEEE_API_KEY, CORE_API_KEY, UNPAYWALL_EMAIL, CROSSREF_MAILTO, and SERPAPI_KEY, so the documentation actively overstates what the code does.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The operational description, headings, parameter explanations, and interaction guidance are written in Chinese, which imposes a specific language on users. The file does not state that the skill is region-specific or provide an opt-in or alternative language path beyond the bilingual title line.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill states that paper data is embedded by default and that previews open in a new tab, but it does not present this as a clear privacy/safety warning to users. In an academic-literature context, embedded HTML may contain metadata, abstracts, or other content that is unintentionally redistributed, and opening generated previews in a new tab can increase accidental exposure of sensitive research datasets or local outputs.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The detectFromProfile method is documented as detecting from a knowledge profile, and it accepts a profilePath, but the implementation ignores the path and constructs a placeholder empty profile instead. This creates a direct mismatch between the advertised behavior of profile-based analysis and the actual code behavior.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
paper-viz/scripts/pdf-figure-extractor.ts:244

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
paper-viz/scripts/ppt-exporter.ts:256

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
shared/ai-provider.ts:29