Back to skill

Security audit

A股/港股/美股数据查询

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly performs disclosed market-data lookups, but it also exposes local portfolio operations that can run an unbundled sibling script and change local holdings data.

Review before installing. Use this only if you are comfortable sending market-data queries to akshare.devtool.uk, and avoid holdings-related prompts unless the portfolio feature has been removed or separately reviewed with clear confirmation and script-integrity controls.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T08 · Insecure Dependencies

Warning
Location
main.py:121
Finding

Execution of an Unverified External Local Dependency

Content
View full analysis

Vulnerability Details

File Location: main.py, lines 121-154
Vulnerability Type: Unverified execution of an adjacent external component
Risk Level: Medium

Vulnerable Code

python
portfolio_script = os.path.join(os.path.dirname(__file__), "..", "a-stock-analysis", "scripts", "portfolio.py")
query = intent_obj.query or ""

if "添加" in query or "add" in query.lower():
    code_match = re.search(r"\b(\d{6})\b", query)
    cost_match = re.search(r"--?cost\s*(\d+\.?\d*)", query)
    qty_match = re.search(r"--?qty\s*(\d+)") or re.search(r"数量\s*(\d+)", query)
    if code_match and cost_match and qty_match:
        result = subprocess.run(
            ["python3", portfolio_script, "add",
             code_match.group(1), "--cost", cost_match.group(1), "--qty", qty_match.group(1)],
            capture_output=True, text=True, timeout=10,
        )
        return {"ok": True, "source": "portfolio", "text": result.stdout or "已添加持仓"}
    return {"ok": False, "error": "请输入:添加持仓 代码 --cost 成本价 --qty 数量\n例如:添加持仓 600519 --cost 10.5 --qty 1000"}

if "分析" in query:
    result = subprocess.run(
        ["python3", portfolio_script, "analyze"],
        capture_output=True, text=True, timeout=60,
    )
    return {"ok": True, "source": "portfolio", "text": result.stdout or "暂无持仓"}

if "删除" in query or "移除" in query:
    code_match = re.search(r"\b(\d{6})\b", query)
    if code_match:
        result = subprocess.run(
            ["python3", portfolio_script, "remove", code_match.group(1)],
            capture_output=True, text=True, timeout=10,
        )
        return {"ok": True, "source": "portfolio", "text": result.stdout or "已删除"}
    return {"ok": False, "error": "请输入要删除的股票代码"}

result = subprocess.run(
    ["python3", portfolio_script, "show"],
    capture_output=True, text=True, timeout=10,
)

Technical Analysis

Portfolio operations execute ../a-stock-analysis/scripts/portfolio.py, a Python file located outside the audited project. The componen ...[truncated 2091 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove the PORTFOLIO route and _handle_portfolio() if portfolio management is not an intended, supported capability.
  2. If the capability is required, bundle the implementation within this project and import a narrowly scoped function instead of executing a sibling Python script.
  3. Resolve the script with os.path.realpath() and verify that it remains inside a trusted, immutable application directory.
  4. Verify component provenance and integrity before use, such as by pinning an approved release and checking a cryptographic digest.
  5. Ensure the script and all parent directories are owned by a trusted account and are not writable by untrusted users or packages.
  6. Run portfolio functionality in a restricted subprocess or sandbox with minimal filesystem, environment, and network access.
  7. Use a minimal environment for any unavoidable subprocess and avoid passing unrelated secrets through inherited environment variables.
  8. Disable portfolio routing by default and require explicit administrative configuration to enable it.
  9. Check subprocess return codes and handle missing or invalid scripts securely rather than reporting unconditional success.
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The documented purpose is market-data lookup, but the analysis indicates additional undeclared capabilities including local portfolio or holdings management and subprocess execution. Hidden state-changing behavior is dangerous because users and orchestrators may invoke the skill assuming it is read-only, while it may actually modify local data or trigger other scripts.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The documented purpose is market-data lookup, but the analysis indicates additional undeclared capabilities including local portfolio or holdings management and subprocess execution. Hidden state-changing behavior is dangerous because users and orchestrators may invoke the skill assuming it is read-only, while it may actually modify local data or trigger other scripts.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares no explicit tool restrictions even though its described operation involves shell execution, network access, and likely environment access. Without a scoped permission boundary, the runtime may permit broader actions than users expect, increasing the chance of unintended command execution or data access if the skill logic is abused or extended.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill instructs forwarding user queries to an external hosted service without an explicit user-facing notice about data transmission. Users may include sensitive investment interests, holdings, or identifiers in free-text queries, and silent forwarding to a third party creates privacy and compliance risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The description says to prefer this skill for direct market data lookups in Chinese, and later the workflow requires producing a Chinese answer. This imposes a specific language/locale behavior without explicit user opt-in or a documented justification that the skill is strictly region/language-bound.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The documentation admits portfolio-management code exists but says it should not be exposed by default, which suggests sensitive capability is present in the same skill boundary. Dormant or non-default dangerous paths still increase risk because prompt steering, routing mistakes, or future changes could activate local state-modifying behavior unexpectedly.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The workflow instructs the agent to turn results into a Chinese answer, regardless of the user's preferred language. That is a natural-language policy issue because it forces a locale/language choice rather than offering or respecting user preference.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill manifest describes a market-data lookup/analysis client, but the code also performs local portfolio management actions that create, analyze, remove, and display user holdings. This scope expansion is dangerous because it introduces undeclared local state-changing behavior, increasing the chance that users or orchestrators invoke capabilities they did not expect or consent to.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill spawns a local subprocess to manage portfolio data even though its stated purpose is hosted market-data lookup. This is risky because local process execution expands the trust boundary from a simple network client to code that can mutate local data and depend on another undeclared script, which may be abused or misused in agent environments.

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 · main.py (reported line 128)May include surrounding context.

python
cost_match = re.search(r"--?cost\s*(\d+\.?\d*)", query)
        qty_match = re.search(r"--?qty\s*(\d+)") or re.search(r"数量\s*(\d+)", query)
        if code_match and cost_match and qty_match:
            result = subprocess.run(
                ["python3", portfolio_script, "add",
                 code_match.group(1), "--cost", cost_match.group(1), "--qty", qty_match.group(1)],
                capture_output=True, text=True, timeout=10,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The code performs add/remove portfolio modifications immediately based on natural-language queries, without any user-facing confirmation, preview, or warning that local state will change. In an agent setting, ambiguous prompts, prompt injection through relayed text, or simple misunderstandings could trigger unintended persistent changes to a user's holdings record.

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 · main.py (reported line 137)May include surrounding context.

python
return {"ok": False, "error": "请输入:添加持仓 代码 --cost 成本价 --qty 数量\n例如:添加持仓 600519 --cost 10.5 --qty 1000"}

    if "分析" in query:
        result = subprocess.run(
            ["python3", portfolio_script, "analyze"],
            capture_output=True, text=True, timeout=60,
        )

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 · main.py (reported line 146)May include surrounding context.

python
if "删除" in query or "移除" in query:
        code_match = re.search(r"\b(\d{6})\b", query)
        if code_match:
            result = subprocess.run(
                ["python3", portfolio_script, "remove", code_match.group(1)],
                capture_output=True, text=True, timeout=10,
            )

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 · main.py (reported line 153)May include surrounding context.

python
return {"ok": True, "source": "portfolio", "text": result.stdout or "已删除"}
        return {"ok": False, "error": "请输入要删除的股票代码"}

    result = subprocess.run(
        ["python3", portfolio_script, "show"],
        capture_output=True, text=True, timeout=10,
    )

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The intent classifier relies almost entirely on Chinese trigger phrases such as "涨停", "分时", "帮助", and "持仓", which effectively forces users into a specific language/locale. There is no visible opt-in, fallback, or documentation in this file indicating that the skill is intentionally limited to Chinese-speaking users or a region-specific context.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
73% confidence
Finding

The manifest describes a narrow flow: run local main.py and send queries to the fixed hosted Akshare service. However, the skill instructions additionally direct the agent to use workspace search tools and Web Search to resolve aliases and symbols, which broadens the capability surface beyond direct market-data lookup via the declared service.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

The recommended workflow and search escalation rules instruct the agent to invoke external search tools when symbol or market mapping is unclear. For a skill presented primarily as a client to a fixed Akshare backend, this expands behavior into general search-assisted fact resolution rather than strictly querying the declared market-data service.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The documentation claims the file sends intents to a cloud service, but some intents are handled locally, including stateful portfolio operations. This mismatch is security-relevant because operators and users may grant trust based on the documented narrow behavior while the code actually has broader local capabilities.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

The natural-language help content is entirely in Chinese and ends with '直接发给我就能查~', implying the skill expects Chinese input without mentioning any language option. This can be a locale/language policy issue because the skill does not offer user opt-in or choice of language.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.