Back to skill

Security audit

Chart Generator Pro

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real ChartGen integration, but it needs review because it can send prompts, files, and API credentials to an overridable endpoint and can download server-provided files without adequate validation.

Review this skill before installing, especially in business or sensitive-data environments. Only use it for data you are willing to send to ChartGen, do not set CHARTGEN_API_URL unless it is a trusted HTTPS ChartGen endpoint, and be aware that generated artifacts are saved locally. The publisher should harden endpoint validation, artifact download validation, permission declarations, and remove promotional error text before this is treated as low-risk.

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 (3)

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

Arbitrary API Endpoint Override Can Disclose API Keys and User Data

Content
View full analysis
{ const parsed = new URL(opts.url); const lib = parsed.protocol === "https:" ? https : http; const reqOpts = { hostname: parsed.hostname, port: parsed.port || (parsed.protocol === "https:" ? 443 : 80), path: parsed.pathname + parsed.search, method: opts.method || "GET", headers: opts.headers || {}, timeout: opts.timeoutMs || 30_000, }; ``` Uploaded files and the API key are sent to the configurable endpoint: ```javascript const res = await request({ url: `${BASE_URL}/api/usl-service/fileTable/upload`, method: "POST", headers: { "Content-Type": `multipart/form-data; boundary=${boundary}`, Authorization: apiKey, "Content-Length": String(body.length), }, body, timeoutMs: 60_000, }); ``` Queries and the API key are also sent to that endpoint: ```javascript const res = await request({ url: `${BASE_URL}/api/agent/chat`, method: "POST", headers: { "Content-Type": "application/json", Authorization: apiKey, }, body, }); ``` Polling requests expose the same credential: ```javascript const res = await request({ url: `${BASE_URL}/api/agent/task/${taskId}`, method: "GET", headers: { Authorization: apiKey }, timeoutMs: 15_000, }); ``` ### Technical Analysis `CHARTGEN_API_URL` is trusted without validating its scheme, hostname, port, or destination. The request ...[truncated 2471 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
tools/chartgen_api.js:358
Finding

Unvalidated Server-Controlled 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); } }); } ``` The URL comes directly from API-controlled artifact metadata: ```javascript } 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 A remote API response controls `art.download_url`, and the tool passes that value to `downloadFile` without validating the scheme, hostname, port, resolved IP address, or path. The implementation has several compounding weaknesses: - Plaintext HTTP downloads are permitted. - Requests to loopback, link-local, private, and internal network destinations are not blocked. - Redirect destinations are not revalidated. - Redirects are followed recursively without a maximum depth. - No response-body size limit is enforced. - No explicit ...[truncated 2901 chars]
Remediation
View remediation
MAX_REDIRECTS) { throw new Error("Too many redirects"); } const parsed = new URL(url); if (parsed.protocol !== "https:") { throw new Error("Only HTTPS artifact downloads are allowed"); } if (!ALLOWED_ARTIFACT_HOSTS.has(parsed.hostname)) { throw new Error("Untrusted artifact host"); } // Resolve and reject local/private addresses before connecting. // Reapply all checks to every redirect destination. // Abort once MAX_BYTES has been received. } ``` Artifact-download failures should be surfaced clearly rather than silently returning `null`, while avoiding disclosure of sensitive internal endpoint details to untrusted users. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

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

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill invokes external tooling and relies on the CHARTGEN_API_KEY environment variable, but the manifest does not declare a restrictive tool scope such as allowed-tools or permissions. This weakens containment and reviewability, making it easier for the skill to gain broader runtime capabilities than users or operators expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The activation conditions are very broad, covering general visualization, analysis, reports, ChartGen mentions, and spreadsheet uploads. This can cause the skill to trigger on many ordinary requests and route user data to an external service unnecessarily, increasing the risk of unintended disclosure or tool use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill sends user queries and uploaded spreadsheet files to an external ChartGen API, but the manifest description does not clearly disclose this data transfer. Users may provide sensitive data without understanding that it will leave the local environment and be processed by a third party.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The tool downloads a remote URL returned by the ChartGen API and writes it to local disk automatically, without validating the destination origin after redirects or clearly surfacing this behavior to the caller/user. In this skill context, the remote service can cause persistent local file creation in the agent media/workspace area, which increases risk of unreviewed content landing on disk and enables SSRF-style fetches to arbitrary URLs if the upstream response is compromised or malicious.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.