Back to skill

Security audit

hekouwang-stock-data-reader-skill

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stock-report purpose, but its report rendering path has unsafe local execution and file-deletion behavior that users should review before installing.

Install only if you are comfortable with a Chinese A-share report pipeline that fetches public market data, writes local CSV/JSON/HTML/PNG files, and embeds the publisher handle in generated images. Until fixed, run it only in a dedicated virtualenv and report directory you control, avoid untrusted company names, filenames, directories, or analysis.json content, and expect matching HTML files to be deleted after screenshots.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T01 · Skill Instruction Hijacking

Error
Location
scripts/build_report.py:78
Finding

Forced Creator Branding in Every Generated Report

Content
View full analysis
' + '
' + ('
%02d
' % idx) + '
财经观察 / 公开数据速读
' + right + '
' + '
' + inner + '
' + '
' + code + ' · %02d/%d
' % (idx, n) + '
会勇禾口王的AI笔记
@huiyonghkw
' + FIT) ``` ### Technical Analysis The `card()` function unconditionally appends the creator's brand and account handle to every generated report card. There is no user-controlled option to disable, replace, or approve this promotional content. Because all report cards pass through this function, the branding is not merely documentation or sample content. It becomes part of every generated HTML report and is subsequently preserved in the PNG deliverables produced by the screenshot stage. This modifies the user's requested output for an unrelated promotional purpose. The repository documentation also directs users to contact the same account for paid output services, reinforcing the commercial redirection effect. ### Attack Path 1. A user asks the Agent to generate a stock-data report. 2. The Agent runs `scripts/build_report.py`. 3. Every report card is passed through `card()`. 4. `card()` inserts the hard-coded creator brand and account handle. 5. `templates/screenshot.js` captures the generated HTML. 6. The promotional content becomes permanently embedded in ...[truncated 380 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
templates/screenshot.js:8
Finding

Shell Command Injection Through Screenshot Directory and Filename Paths

Content
View full analysis
/^\d{2}-.*\.html$/.test(f)).sort(); for (const file of files) { const htmlPath = path.join(dir, file); const outPath = path.join(outDir, file.replace('.html', '.png')); const cmd = `"${chrome}" --headless=new --allow-file-access-from-files --disable-gpu --no-sandbox --window-size=${W},${H} --hide-scrollbars --force-device-scale-factor=2 --screenshot="${outPath}" --virtual-time-budget=6000 "file://${htmlPath}"`; try { execSync(cmd, { stdio: 'pipe', timeout: 45000 }); ``` ### Technical Analysis The script constructs a shell command by concatenating path values into a string and passes that string to `execSync()`. Both the directory argument from `process.argv[2]` and filenames discovered in that directory can influence `htmlPath` and `outPath`. Although these paths are enclosed in double quotes, shell command substitution remains active inside double-quoted strings. Path components containing syntax such as `$(command)` can consequently execute commands when the command string is interpreted by the shell. The filename filter only checks that a filename starts with two digits and ends with `.html`. It does not exclude shell metacharacters or command-substitution expressions. ### Attack Path 1. An attacker creates or supplies a report directory whose literal path contains shell command-substitution syntax, such as a component equivalent to `$(touch /tmp/agent-owned)`. 2. The attacker causes the Agent to invoke: ```text node templates/screenshot.js ``` 3. `path.resolve()` preserves the crafted characters in the resolved path. 4. The ...[truncated 844 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/build_report.py:175
Finding

Unescaped Report Data Is Rendered in an Unsandboxed Browser

Content
View full analysis
%s %s · 公开数据速读' '

用数据,
看清一只票

' '

不预测后市,只把资金怎么流的、公司什么成色用公开数据摆清楚。

' '
%s
' % (nm, code, gh))) ``` The completed markup is written without sanitization: ```python with open(os.path.join(outdir, fn), "w", encoding="utf-8") as fobj: fobj.write(card(i, n, code, right, inner, theme)) ``` The generated document is then opened with weakened Chrome security controls: ```javascript const cmd = `"${chrome}" --headless=new --allow-file-access-from-files --disable-gpu --no-sandbox --window-size=${W},${H} --hide-scrollbars --force-device-scale-factor=2 --screenshot="${outPath}" --virtual-time-budget=6000 "file://${htmlPath}"`; ``` ### Technical Analysis The optional company name is accepted from the command line and assigned to `nm` without validation or HTML escaping. It is then interpolated directly into an HTML fragment. Other text fields originating from generated JSON, including business-segment names, are also inserted into HTML or SVG strings without a consistent escaping boundary. An attacker-controlled value containing markup, such as a closing element followed by a `
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Mutable and Unhashed Third-Party Dependency Installation

Content
View full analysis
=1.18,<2.0 pandas>=2.0,<3.0 ``` The bootstrap process installs whatever versions currently satisfy those ranges and also upgrades packaging tools: ```bash python -m pip install -U pip wheel pip install -r requirements.txt ``` ### Technical Analysis The dependency file uses broad version ranges rather than exact reviewed versions and does not provide cryptographic hashes. Running the bootstrap process at different times can therefore install different code than the code considered during this audit. The unconditional upgrade of `pip` and `wheel` adds further mutable packages to the installation process. Python package installation can execute package build logic, and imported dependencies subsequently execute with the full privileges of the Agent process. No evidence was found that the named packages are intentionally malicious or typosquatted. The issue is the absence of an immutable, verifiable dependency set, which increases exposure to a future compromised release, malicious distribution artifact, or incompatible dependency change. ### Attack Path 1. A user follows the documented bootstrap workflow. 2. `pip` resolves the latest available versions satisfying the broad ranges. 3. A newly published or compromised artifact within an allowed range is selected. 4. The package is downloaded without verification against a repository-maintained hash. 5. Installation-time build logic or later imported package code executes as the user running the Skill. ### Impact Assessment A compromised dependency could execute code with the same privileges as the Agent process. This could expose files, environment variables, generated reports, and network access available to that user. The finding represents supply-ch ...[truncated 84 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This code chunk does not implement the declared stock data reading and financial recap functionality. Instead, it is a rendering helper for converting HTML templates into PNG screenshots. While image generation could be a supporting part of producing finance posters, the chunk shown only performs screenshotting and file deletion; it contains none of the core declared behavior such as fetching market data, calculating metrics, applying financial compliance guardrails, or generating neutral recap text. It also introduces undeclared filesystem deletion behavior (removing HTML files after success). Therefore the code's actual behavior is materially different from the declared purpose for this skill.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
75% confidence
Finding

The skill uses 'env' capability that is not listed in its permissions. This may indicate deceptive intent or missing permission declarations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code builds a shell command and launches a local Chrome binary in headless mode with --no-sandbox and --allow-file-access-from-files, then opens attacker-controlled local HTML. In this context, rendered HTML can execute active browser content with weakened isolation and local file access privileges, which materially increases the risk of local data exposure or browser-based compromise beyond the stated reporting purpose.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The changelog and linked documentation references are presented entirely in Chinese, including the heading and process descriptions, with no indication that users may choose another language. Under the policy, forcing a specific language or locale without user opt-in is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README states that after installation, the agent will 'automatically' recognize the skill and that the user can speak in ordinary natural language to trigger a full pipeline. This broad invocation model increases the chance of unintended activation on ambiguous requests, causing unnecessary data retrieval, report generation, or publication-oriented workflow steps without explicit user confirmation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The natural-language description specifies output forms such as WeChat/Toutiao posts and uses Chinese-only publication constraints, without stating that the user may choose language or locale. This can violate language/locale policy when the skill is used in broader contexts where the user has not opted into Chinese output.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The listed trigger phrases include broad natural-language requests such as "扒公司公开数据", "资金面复盘", and "出个股报告", which could match ordinary user requests rather than a narrowly scoped skill invocation. The description does not provide exclusion conditions or negative examples to clarify when the skill should not activate.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The file is entirely written as a fixed Chinese reporting template and specifies report structure, copy style, and workflow in Chinese, but does not indicate any user opt-in or alternative language option. Under the policy, forcing a specific language without user choice is a natural-language policy violation unless the locale constraint is explicitly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code file contains natural-language instructions entirely in Chinese, including the module docstring and command usage, with no indication that users may choose another language or locale. The policy requires flagging language or locale constraints when a skill effectively forces a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The ImportError exit message is presented only in Chinese, and similar Chinese-only user-facing messages appear elsewhere in the script. Because this is natural-language output that users must read to operate the skill, it constitutes a language policy issue when no alternative language or opt-in is provided.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script's completion notice and CLI usage guidance are emitted only in Chinese, which forces one language for end users. The stated policy says to flag language or locale restrictions unless the file offers user choice or clearly documents a justified regional constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The module docstring specifies the skill's report-generation behavior entirely in Chinese and describes a Chinese public-account output format, indicating the skill is designed to produce Chinese-language deliverables by default. There is no accompanying language choice, opt-in, or justification that this is a region-specific tool, which can violate language/locale policy requirements.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module docstring, usage messages, and operational output are written entirely in Chinese, which imposes a language choice on users. Under the stated policy, forcing a specific language without opt-in is a natural-language locale violation unless the tool is explicitly documented as region- or language-specific.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script unconditionally deletes each source HTML file immediately after a successful screenshot, which creates a destructive side effect not implied by a stock-data reading/report-generation skill. If the directory argument is broader than intended or the generated HTML is needed for auditing, debugging, or regeneration, this causes silent data loss and reduces recoverability.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Deleting source HTML without any runtime notice, prompt, or confirmation is an unsafe quality and safety issue because users may reasonably expect a screenshot tool to be non-destructive. In a skill focused on generating stock-report artifacts, silent deletion undermines traceability, reproducibility, and post-run review, and could destroy user work if pointed at the wrong directory.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The usage section instructs users to '对 Claude 说人话' and provides only Chinese prompt examples, while the skill description throughout is framed around Chinese-language output formats like 公众号 and 头条. There is no indication that users may choose another language or that the Chinese-only scope is an intentional, documented locale constraint.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: pandas has 1 known advisory(ies) (CVE-2020-13091 (** DISPUTED ** pandas through 1.0.3 can unserialize and execute commands from an)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script’s natural-language content, including the header comment and all user-facing echo messages, is written only in Chinese. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is clearly justified.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script derives a path outside its own skill and allows an environment variable to override the font directory, then embeds those file paths into generated HTML. This creates unnecessary cross-skill filesystem coupling and could be abused to reference unintended local files or sensitive paths during rendering/screenshot workflows, even though the immediate use is only for fonts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code persists fetched data to disk via to_csv, which affects user filesystem state. Although the top-level docstring describes that data will be saved, there is no runtime confirmation or user-facing warning before the first write, and the same pattern continues for several output files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The script makes outbound requests through akshare to retrieve stock and financial data. While comments mention network constraints and the docstring states the data source is public, there is no explicit runtime disclosure that the script will contact external services and may transmit requested stock symbols and environment-derived network metadata.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/fetch.py (reported line 65)May include surrounding context.

python
# 3) 估值历史 PE/PB/市值band(不同 akshare 版本函数名不同,按序回退)
    def _valuation():
        for fn in ("stock_value_em", "stock_a_indicator_lg"):
            f = getattr(ak, fn, None)
            if f is None:
                continue
            try:

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
templates/screenshot.js:17