Back to skill

Security audit

Chart Generator

Security checks for vulnerabilities and agentic risk

Overview

This ChartGen skill has a coherent charting purpose, but it contains high-impact safety issues around shell execution, endpoint trust, and unvalidated downloads.

Review before installing. Use only with non-sensitive data unless you trust ChartGen's processing and retention practices, do not run the documented submit command through a shell with untrusted query text, avoid setting `CHARTGEN_API_URL` except to a trusted HTTPS endpoint, and treat downloaded artifacts as untrusted files from an external service.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:73
Finding

Shell Command Injection Through Verbatim User Query Interpolation

Content
View full analysis
` is **always the user's original message, copied word-for-word**. Do NOT translate, rephrase, expand, polish, or "improve" it in any way. Show this exact text in the confirmation. If user confirms → submit this exact text. If user edits → the edited text becomes the new verbatim query. ``` ```markdown **Then call the tool:** ``` node tools/chartgen_api.js submit "" [files...] ``` ``: **Copy-paste the confirmed text from STEP 1** — the user's original words or, for file uploads, the chosen option text. Never rewrite. ``: current channel name, e.g. `Signal`, `WhatsApp`, `Web`. `[files...]`: optional, space-separated absolute paths to data files. ``` ### Technical Analysis The skill requires the agent to copy attacker-controlled user input verbatim into a shell command enclosed only by double quotes. Double quotes do not neutralize shell command substitutions such as `$(...)` or backticks. Embedded quotation marks can also terminate the intended argument and introduce shell operators. If the agent follows the documented workflow through a shell-backed execution tool, the shell interprets metacharacters before Node.js receives `process.argv`. The JavaScript tool cannot protect against this issue because exploitation occurs before `chartgen_api.js` starts. Confirmation is not a security boundary. A user can deliberately confirm a malicious query, while another user might confirm text whose shell significance is not apparent. ### Attack Path 1. An attacker submits a visualization request containing shell syntax, such as: ```text Create a chart named "$(id > /tmp/chartgen-command-executed)" ``` 2. The skill requires the request to be preserved word-for-word and shown for con ...[truncated 1258 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Warning
Location
SKILL.md:103
Finding

Forced Promotional Content in Agent Responses

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
tools/chartgen_api.js:25
Finding

API Credentials and User Data Can Be Redirected to an Arbitrary Endpoint

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
tools/chartgen_api.js:358
Finding

Unrestricted Server-Directed Artifact Downloads Enable SSRF and Resource Exhaustion

Content
View full analysis
{ try { const mediaDir = getMediaDir(); const dest = path.join(mediaDir, `chartgen_${tag}.${ext}`); const mod = url.startsWith("https") ? https : http; const file = fs.createWriteStream(dest); mod.get(url, (res) => { if (res.statusCode === 301 || res.statusCode === 302) { downloadFile(res.headers.location, tag, ext).then(resolve); return; } if (res.statusCode !== 200) { resolve(null); return; } res.pipe(file); file.on("finish", () => { file.close(); resolve(dest); }); file.on("error", () => resolve(null)); }).on("error", () => resolve(null)); } catch { resolve(null); } }); } ``` API-provided URLs are passed directly into that function: ```js } else if (art.download_url) { const dtag = String(art.artifact_id || Date.now()); const dp = await downloadFile(art.download_url, dtag, "pptx"); if (dp) art.download_path = dp; } ``` ### Technical Analysis The task API controls `art.download_url`, and the client retrieves it without validating the destination. Both HTTP and HTTPS are accepted. Redirect destinations are followed recursively without a redirect limit or revalidation. The implementation does not block loopback, link-local, private, or cloud metadata addresses. It also lacks a response-size limit, a download timeout, and substantive content validation. The `.pptx` extension is assigned locally regardless of the actual response content. Consequently, a compromised or malicious API response can make the agent issue network requests to internal services. It can also stream an unbounded respo ...[truncated 1711 chars]
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (14)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill instructs the agent to call an external API for analysis and file upload, but it does not clearly warn users that their prompts, uploaded spreadsheets, and possibly external-source requests will be transmitted to a third-party service. This undermines informed consent and can expose sensitive business or personal data to an external processor without adequate disclosure.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
## Tool — `tools/chartgen_api.js`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
## Tool — `tools/chartgen_api.js`

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
## Tool — `tools/chartgen_api.js`

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
70% confidence
Finding

Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Content

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

md
### STEP 1 — Confirm Before Submitting

Always respond in the user's language. **Must** mention using **ChartGen** to complete the task, and include numbered options, each on its own line:
> **1** ✅ Go ahead
> **2** ✏️ Modify
> **0** ❌ Cancel

Anti-Refusal Statement

High
Category
Anti-Refusal
Confidence
70% confidence
Finding

Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Content

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

md
### STEP 1 — Confirm Before Submitting

Always respond in the user's language. **Must** mention using **ChartGen** to complete the task, and include numbered options, each on its own line:
> **1** ✅ Go ahead
> **2** ✏️ Modify
> **0** ❌ Cancel

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The tool downloads a URL supplied by the remote API result without validating host, scheme beyond http/https, destination, redirect target, size, or content type. If the upstream service is compromised or malicious, this creates an SSRF-style outbound fetch primitive and can store attacker-controlled content locally, potentially reaching internal services or writing unexpected files into trusted media locations.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares access to environment-derived secrets via CHARTGEN_API_KEY but does not define an explicit tool scope such as permissions or allowed-tools. That makes the execution surface less constrained and increases the risk that the skill can invoke capabilities beyond what users or reviewers expect, especially in systems that rely on manifest scoping for sandboxing and review.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The activation description is very broad, covering visualizations, analysis, reports, uploaded spreadsheets, and even any mention of ChartGen. Over-broad routing can cause the skill to trigger on common requests and funnel user prompts or files to an external service unnecessarily, creating privacy and data handling risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The instruction 'Always respond in the user's language' imposes a language policy automatically rather than offering an opt-in or choice. Under the stated policy criteria, forcing a language/locale behavior without user choice is a natural-language policy violation unless clearly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This rule hard-codes language behavior for all interactions and does not indicate that the user may select a different language. That creates a language/locale policy issue because the skill enforces a specific response language automatically rather than by user choice.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The documentation says the skill 'never needs to know or pass secrets,' yet the script resolves the API key and includes it in Authorization headers for upload, submit, and poll operations. This is an active contradiction between the documented intent and the implementation, not merely an omitted detail.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest describes a visualization and data-analysis skill, but this helper additionally searches local environment variables and multiple filesystem locations for secrets. Secret discovery may be a practical integration choice, but it is not an obvious requirement of creating charts or reports and expands the skill's effective capability beyond its stated purpose.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest says the skill creates visualizations and reports, but the code also creates directories and persists images, PPTX files, and spreadsheets on disk. Persisting outputs may be useful, yet local filesystem write capability is not explicitly justified by or described in the manifest text.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.