Back to skill

Security audit

Market Chart Renderer

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real chart renderer, but it needs review because it can write files outside its documented output folder and its generated charts execute mutable remote JavaScript.

Review before installing. Use it only in a workspace where generated files are acceptable, do not pass untrusted --output-stem values, and prefer fixing path containment, safe HTML data embedding, and a pinned or local ECharts dependency before relying on its output.

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

T09 · Insecure Skill Coding Practices

Error
Location
render_chart.py:316
Finding

Arbitrary File Write Through Unsanitized Output Stem

Content
View full analysis
Remediation
View remediation
Path: if not re.fullmatch(r'[A-Za-z0-9._-]+', output_stem): raise ValueError('output stem contains unsupported characters') root = OUTDIR.resolve() candidate = (root / output_stem).resolve() if candidate.parent != root: raise ValueError('output path escapes the output directory') return candidate ``` - Apply the containment check independently to every final path before writing. - Consider exclusive file creation or an explicit overwrite option if existing files must not be replaced silently. - Run the renderer under a dedicated, least-privileged account with write access limited to the intended output directory. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
render_chart.py:273
Finding

JavaScript Injection Through Unsafe JSON Embedding in Generated HTML

Content
View full analysis
str: option = build_option(payload) option_json = json.dumps(option, ensure_ascii=False) payload_json = json.dumps(payload, ensure_ascii=False) return f''' Market Chart Renderer html, body {{ margin: 0; width: 1400px; height: 900px; background: #0b1220; overflow: hidden; }} #chart {{ width: 1400px; height: 900px; }}
''' ``` ### Technical Analysis `payload_json` and `option_json` contain values derived from chart and instrument data. They are serialized as valid JSON and inserted directly into an inline HTML ``. The browser recognizes that sequence as the end of the script element even when it appears inside a JavaScript string literal. Consequently, an attacker-controlled string such as the following can terminate the intended script and inject markup or JavaScript: ```text ``` Potentially affected values include strings propagated from the upstream chart payload, such as instrument contract, ...[truncated 1433 chars]
Remediation
View remediation
` with `\u003e` - `&` with `\u0026` - U+2028 with `\u2028` - U+2029 with `\u2029` - For example: ```python def script_safe_json(value: Any) -> str: return ( json.dumps(value, ensure_ascii=False) .replace('&', '\\u0026') .replace('<', '\\u003c') .replace('>', '\\u003e') .replace('\u2028', '\\u2028') .replace('\u2029', '\\u2029') ) ``` - Prefer storing serialized data in a non-executable ``, HTML tags, quotes, U+2028, and U+2029 in every externally derived string field. ]]>

T08 · Insecure Dependencies

Warning
Location
render_chart.py:290
Finding

Execution of Mutable Third-Party JavaScript From an Unpinned CDN Dependency

Content
View full analysis
``` ### Technical Analysis Every generated chart references ECharts from a public CDN at runtime. The dependency uses the floating major-version selector `@5` rather than an exact immutable version. It also lacks a Subresource Integrity hash. As a result, the JavaScript executed when the chart is opened or rendered is not fully represented by the audited project. A future package release, compromised package publication, CDN compromise, or unexpected CDN resolution behavior could cause different JavaScript to execute without any local source-code change. The same dependency is loaded during headless Chrome PNG generation, making chart rendering dependent on both network availability and the current content returned by the external service. ### Attack Path 1. A user runs the renderer, which generates an HTML file containing the remote script reference. 2. The HTML is opened interactively or loaded by headless Chrome during PNG generation. 3. The browser requests `echarts.min.js` from jsDelivr. 4. The CDN resolves the floating `@5` selector and returns JavaScript not cryptographically verified by the generated page. 5. If the package or delivery path has been compromised, the browser executes the substituted JavaScript in the chart document. 6. The substituted code can manipulate the generated visualization, initiate network traffic, and access information available to that browser document. ### Impact Assessment A compromised dependency can execute JavaScript in every generated chart at view or rendering time. This can undermine chart integrity, falsify screenshots, disclose chart payload data over the network, and make rendering behavior change afte ...[truncated 366 chars]
Remediation
View remediation
``` - Record the exact dependency version and hash in project dependency metadata. - Restrict permitted script origins with Content Security Policy. - Ensure PNG rendering can operate offline so output generation does not silently depend on mutable external content. - Include dependency update review and integrity-hash regeneration in the release process. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (10)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises capabilities that involve shell execution and writing files, but it does not declare any explicit tool scope or permission boundaries. That omission increases the chance that an agent invokes the skill with broader-than-necessary privileges, leading to unintended command execution or filesystem modification if downstream scripts are misused.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

SQP-3 covers natural-language policy violations such as forcing a specific language or locale without user opt-in. The summary explicitly frames the skill as 中国市场 and the document is entirely in Chinese, with no indication that users may choose another language or that the locale restriction is optional.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

A skill named market-chart-renderer is justified in transforming provided market data into visual outputs, but this file also reaches into another skill module and calls build_chart_payload to obtain the underlying chart data. That cross-skill data acquisition capability is not an obvious requirement of a renderer if its stated purpose is only rendering charts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The runtime warning text is hard-coded in Chinese, and other user-visible strings in the generated chart are also fixed in Chinese, with no option to select language or locale. This is a natural-language policy issue because the skill imposes a specific language on all users without opt-in or documented locale scope.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The chart title text includes fixed Chinese labels such as '最新', and the series name at L232 uses 'K线', making the rendered output language-specific. Because the file offers no localization setting or opt-in, it forces a specific language in user-visible output.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The generated HTML loads ECharts from a remote CDN at render time, which introduces undeclared network access and a supply-chain trust dependency into what otherwise appears to be a local renderer. Because the HTML is then opened in headless Chrome for screenshot generation, a compromised CDN response or unexpected network behavior could influence execution inside the browser context.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Loading a remote JavaScript library without notifying the user that rendering triggers network access is a real security-relevant transparency issue, especially in tooling expected to operate locally. In a security-sensitive or offline environment, undisclosed outbound requests can leak usage metadata and create an avoidable external execution dependency.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · render_chart.py (reported line 318)May include surrounding context.

python
f'--screenshot={png_path}',
        html_path.resolve().as_uri(),
    ]
    subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    return chrome_binary

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

For markdown files, SQP-2 applies when the skill description omits warnings about behaviors that can affect user data or system state. This file documents output paths under output/generated/images/* but does not warn that running the skill will create or replace files there.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

This code performs file writes to generated output paths, including HTML and JSON unconditionally and PNG conditionally, but the write operations themselves have no confirmation prompt, warning print, or inline comment/docstring explaining that files will be created. For code files, file writes are in scope when they lack any form of user disclosure and are not explicitly surfaced at the point of action.

Content

No source excerpt is available for this finding.