Back to skill

Security audit

Stock Selecter

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stock-screening purpose, but it handles a user API token insecurely and has misleading financial-strategy logic that users should review before installing.

Install only if you are comfortable reviewing and fixing the HTTP API endpoint first, treating all output as research rather than investment advice, and controlling where result files are saved. Rotate any Tushare token previously used with this version over HTTP.

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
stock_utils.py:26
Finding
Tushare API Token Transmitted over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `stock_utils.py:26-110` **Vulnerability Type**: Cleartext transmission of sensitive credentials **Risk Level**: High ### Vulnerable Code ```python TUSHARE_API_URL = "http://api.tushare.pro" ``` ```python payload: Dict[str, Any] = { "api_name": api_name, "token": token, "params": params, } if fields: payload["fields"] = fields headers = {"Content-Type": "application/json"} for attempt in range(retries + 1): try: response = requests.post( TUSHARE_API_URL, json=payload, headers=headers, timeout=DEFAULT_TIMEOUT, ) ``` ### Technical Analysis The application places the user's Tushare API token in a JSON request body and sends it to an `http://` endpoint. HTTP provides neither transport confidentiality nor server authentication. It also does not protect response integrity. An attacker able to observe or modify traffic between the host and the API can: - Read and reuse the Tushare token. - Modify API request parameters. - Substitute market data in API responses. - Inject attacker-controlled strings into fields later included in JSON, CSV, or HTML reports. - Redirect or disrupt requests without being detected by TLS certificate validation. A timeout does not provide any confidentiality or integrity protection. The fact that the hostname is documented as the official API does not make a plaintext connection secure. ### Attack Path 1. A user configures a valid Tushare token in `config.json` or the `TUSHARE_TOKEN` environment variable. 2. The user runs a screening strategy. 3. `call_api()` adds the token to the JSON payload. 4. The application sends the payload over plaintext HTTP. 5. An attacker controlling or monitoring the local network, proxy, gateway, DNS path, or another relevant intermediary captures the request. 6. The attacker extracts and reuses the token, or modifies the API response before it reaches the applicatio ...[truncated 804 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the plaintext endpoint with the verified HTTPS endpoint: ```python TUSHARE_API_URL = "https://api.tushare.pro" ``` 2. Keep TLS certificate validation enabled. Do not set `verify=False` or install an unrestricted custom certificate bypass. 3. Reject redirects that downgrade the connection from HTTPS to HTTP. Consider disabling automatic redirects or explicitly validating every redirect target. 4. Restrict the destination hostname to the intended Tushare API host. 5. Rotate all API tokens that may previously have been transmitted through the HTTP endpoint. 6. Store the token outside the project tree, preferably in an environment variable or an operating-system credential store. 7. Add an automated test that fails when the configured API URL does not use HTTPS. 8. Avoid logging request payloads or authorization material, including in future debug changes. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
utils/report.py:77
Finding
Stored HTML Injection in Generated Stock Reports<![CDATA[ ## Vulnerability Details **File Location**: `utils/report.py:77-130` **Vulnerability Type**: Unescaped HTML generation and stored script injection **Risk Level**: Medium ### Vulnerable Code ```python lines = [] for i, r in enumerate(items, 1): ts_code = r.get("ts_code", "") name = r.get("name", ts_code) score = r.get("score", 0) strategies_hit = r.get("strategies_hit", []) industries = r.get("industry", "") score_color = _score_color(score) strategies_label = ", ".join(strategies_hit) if strategies_hit else r.get("strategy", "") extra_cells = _build_extra_cells(r, strategies_hit) lines.append( f"<tr>" f"<td>{i}</td>" f"<td class='code'>{ts_code}</td>" f"<td class='name'>{name}</td>" f"<td>{industries}</td>" f"<td class='score' style='color:{score_color}'>{score:.1f}</td>" f"<td class='strategies'>{strategies_label}</td>" f"{extra_cells}" f"</tr>" ) ``` ```python def _build_extra_cells(r: Dict, strategies_hit: List[str]) -> str: cells = [] for s in strategies_hit: if s == "roe": cells.append(f"<td>{r.get('roe', '-')}</td>") elif s == "dividend": cells.append(f"<td>{r.get('dv_ratio', '-')}%</td>") elif s == "valuation": cells.append(f"<td>PE {r.get('pe_ttm', '-')}</td>") cells.append(f"<td>PB {r.get('pb', '-')}</td>") elif s == "growth": cells.append(f"<td>Revenue {r.get('revenue_growth', '-')}%</td>") elif s == "macd": cells.append(f"<td>Volume {r.get('surge_ratio', '-')}x</td>") elif s == "low_position_surge": cells.append(f"<td>Percentile {r.get('price_pct_rank', '-')}%</td>") elif s == "trend": cells.append(f"<td>ADX {r.get('adx', '-')}</td>") elif s == "pattern": patterns = r.get("patterns", []) cells.append(f"<td>{', '.join(patterns) ...[truncated 2170 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Escape every dynamic textual value before placing it in HTML: ```python from html import escape safe_code = escape(str(ts_code), quote=True) safe_name = escape(str(name), quote=True) safe_industry = escape(str(industries), quote=True) safe_strategies = escape(str(strategies_label), quote=True) ``` 2. Apply escaping inside `_build_extra_cells()` to pattern labels and all values that are not guaranteed numeric. 3. Validate structured fields before rendering: - Restrict stock codes to the expected exchange-code format. - Allow only registered strategy identifiers. - Require numeric indicator fields to be finite numbers. - Restrict pattern labels to known internal values. 4. Prefer a maintained template engine with automatic HTML escaping instead of manual string concatenation. 5. Add a restrictive Content Security Policy, for example one that disallows inline and remote scripts. 6. Add regression tests using values containing `<`, `>`, `"`, `'`, event handlers, and script elements. 7. Enforce HTTPS for the upstream API so an on-path attacker cannot inject report content through modified responses. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Unbounded Dependency Versions Reduce Supply-Chain Integrity<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-5` **Vulnerability Type**: Unpinned third-party dependencies **Risk Level**: Low ### Vulnerable Code ```text tushare>=1.4.0 requests>=2.25.0 pandas>=1.3.0 numpy>=1.20.0 scipy>=1.7.0 ``` ### Technical Analysis Every dependency is specified only with a minimum version. As a result, a future installation can retrieve any later version satisfying the constraint, including major versions that were never reviewed or tested with this project. The dependency names are mainstream packages, and no suspicious package source, typosquatted package, or known malicious package was identified during this audit. The issue is therefore one of supply-chain hardening and reproducibility rather than evidence of an intentionally malicious dependency. Python packages and their build systems may execute code during installation or import. If a future accepted release is compromised, malicious, or unexpectedly incompatible, installing from this file can introduce that code without any change to the audited project. ### Attack Path 1. A user runs `pip install -r requirements.txt`. 2. The package resolver selects the newest available versions that satisfy the lower-bound constraints. 3. A selected version differs from the versions reviewed by the project maintainers. 4. If that release or its transitive dependencies are compromised, malicious installation or import behavior executes under the privileges of the user performing the installation. 5. Alternatively, an incompatible future release may change data handling or security behavior and silently undermine the application. ### Impact Assessment Potential impact depends on the behavior and installation context of a compromised dependency. Package installation code generally runs with the privileges of the invoking user and could access that user's files, environment variables, network, and application credentials. No concrete malicious dependency was fo ...[truncated 151 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin all direct dependencies to reviewed versions. 2. Generate and commit a lock file that includes transitive dependencies. 3. Use hash verification, such as `pip install --require-hashes`, to ensure downloaded artifacts match reviewed packages. 4. Update dependencies through a controlled process with automated tests and security review. 5. Run vulnerability and license scanning against both direct and transitive packages. 6. Install dependencies in an isolated virtual environment under a non-privileged account. 7. Configure the package installer to use only an approved package index and trusted repository. ]]>
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 (63)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill explicitly says requests for specific stock codes/names and pure data queries should be excluded, yet the documented behavior and return schema show direct per-stock handling and local JSON persistence. In an agent pipeline, this kind of description-behavior mismatch can bypass routing expectations, causing the skill to process data types it was supposed to refuse and to write outputs locally without clear consent.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill explicitly says requests for specific stock codes/names and pure data queries should be excluded, yet the documented behavior and return schema show direct per-stock handling and local JSON persistence. In an agent pipeline, this kind of description-behavior mismatch can bypass routing expectations, causing the skill to process data types it was supposed to refuse and to write outputs locally without clear consent.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The skill explicitly says requests for specific stock codes/names and pure data queries should be excluded, yet the documented behavior and return schema show direct per-stock handling and local JSON persistence. In an agent pipeline, this kind of description-behavior mismatch can bypass routing expectations, causing the skill to process data types it was supposed to refuse and to write outputs locally without clear consent.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The skill explicitly says requests for specific stock codes/names and pure data queries should be excluded, yet the documented behavior and return schema show direct per-stock handling and local JSON persistence. In an agent pipeline, this kind of description-behavior mismatch can bypass routing expectations, causing the skill to process data types it was supposed to refuse and to write outputs locally without clear consent.

Missing User Warnings

High
Confidence
99% confidence
Finding
The module sends the Tushare token and all request parameters to http://api.tushare.pro over plaintext HTTP, exposing credentials and financial query data to interception or tampering by any network adversary on the path. In an agent-integrated environment, this can lead to credential theft, manipulated API responses, and downstream integrity issues in stock-screening results.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The strategy is labeled and marketed as detecting shareholder/executive share increases, but the implementation primarily queries the `repurchase` API, which represents company buybacks rather than insider or major-holder增持. In a stock-selection skill, this semantic mismatch can directly mislead downstream investment decisions, causing users to act on materially incorrect signals while believing they are screening a different corporate action.

Intent-Code Divergence

High
Confidence
96% confidence
Finding
The comments explicitly acknowledge that the chosen interface does not provide shareholder/executive增持 data, yet the function still processes and returns results as if it were an增持 strategy. This contradiction indicates known misrepresentation in the logic path, which is especially risky in a financial screening context because users and other components will trust the output labels and rankings as accurate.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The skill manifest presents a broader strategy set and trigger surface than the code documentation in this file. README.md describes an A-share stock selector with 11 independent strategies, and its strategy table omits several manifest-claimed capabilities such as 北向资金、股东增持、分析师目标价 and others, indicating a mismatch between claimed behavior and documented implementation scope.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill documents capabilities that imply environment access, local file read/write, and network use, but it does not declare any tool scope or permissions boundaries. In an agent setting, missing explicit scope increases the risk of over-broad tool access, unintended data exfiltration, or filesystem writes beyond user expectations.

Description-Behavior Mismatch

Medium
Confidence
83% confidence
Finding
The manifest says requests involving specific stock codes/names are excluded, but examples and return data clearly operate on named stocks and stock identifiers. In agent orchestration, such contradictory contract language can break policy-based routing and cause the skill to handle inputs it should refuse, potentially exposing or persisting unintended data.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill states that screening results and HTML reports are automatically saved to local disk, including to a fixed external-drive path, without a clear warning or consent flow. Automatic file creation can expose sensitive financial research, surprise users, leak data onto shared or removable storage, and create persistence where none was expected.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
Natural-language strings throughout the file, including the module description, CLI help text, status messages, and result summary, are presented only in Chinese. The policy for this audit flags locale/language constraints when a skill forces a specific language without user opt-in or documented justification.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
Natural-language strings in the module docstring and user-facing messages are exclusively Chinese, which effectively forces a specific language without user opt-in. The file does not indicate that this is an intentionally region-specific skill or provide any language selection.

External Transmission

Medium
Category
Data Exfiltration
Content
for attempt in range(retries + 1):
        try:
            response = requests.post(
                TUSHARE_API_URL,
                json=payload,
                headers=headers,
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The utility module exposes arbitrary local file write via save_json_data(data, filename), allowing callers to write attacker-influenced content to any path the process can access. In an agent skill context, generic file-write capability is broader than the advertised stock-screening purpose and could be abused for overwriting local data, planting files, or persisting untrusted outputs.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The `_calc_target` docstring describes the strategy as '目标价 = 当年预测EPS × 历史行业PE中位数', which implies use of an industry-based valuation benchmark. However, the implementation never fetches or computes any industry PE median; it either multiplies EPS by the forecast PE from the data or derives a target by applying a 20% premium to the stock's implied current PE. This is an active contradiction between documentation and behavior, not merely an omitted detail.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The function claims to measure consecutive dividend years, but it only counts distinct years present in financial records. In a stock-selection skill, this can materially misclassify equities as having stable dividend histories when no dividend evidence was checked, leading to misleading outputs and potentially harmful financial decisions.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
The payout-ratio function documents a financial estimate but returns an almost constant value derived from dv_ratio divided by itself, which is effectively ~100% for nearly all inputs. This undermines scoring integrity and can systematically distort recommendations in a finance-related skill, making the output unreliable in a way users may not notice.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
The module docstring is entirely in Chinese, and the rest of the inline comments and returned labels are also Chinese-only. For a general-purpose skill file, this imposes a specific language/locale without any visible opt-in, fallback, or documented region-specific constraint.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The manifest presents this as a 北向资金选股 strategy focused on northbound capital flow signals, but the implementation also fetches financial indicator data and incorporates ROE into the final score. That introduces a cross-strategy fundamental factor not justified by the stated strategy description, changing behavior from pure capital-flow screening to mixed factor scoring.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The module docstring uses Chinese-only natural-language descriptions, and additional Chinese-only comments and docstrings appear later in the file. Under the policy rule, forcing a specific language without user opt-in or justification is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
The file's natural-language docstrings and user-facing ImportError message are entirely in Chinese, which imposes a specific language on users and maintainers without offering any opt-in or alternative. Under the stated policy, forcing a specific language without user choice is a locale/language policy violation unless clearly justified as region-specific.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
sys.path.insert(0, ws_root)

    try:
        __import__("stock_utils")
        __import__("stock_indicators")
        return ws_root or skill_dir or ""
    except ImportError:
Confidence
95% confidence
Finding
The loader modifies sys.path using directories discovered by walking parent paths, then imports modules by name. This can cause Python to load attacker-controlled stock_utils.py or stock_indicators.py from an unintended location in the workspace tree, resulting in arbitrary code execution at import time if a malicious file is present.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Content
try:
        __import__("stock_utils")
        __import__("stock_indicators")
        return ws_root or skill_dir or ""
    except ImportError:
        raise ImportError(
Confidence
95% confidence
Finding
This import has the same risk pattern as the previous one: once sys.path is prepended with a discovered parent directory, importing stock_indicators by name may execute code from an attacker-planted module outside the intended skill directory. Because Python executes top-level module code during import, exploitation can occur immediately without further checks.

Natural-Language Policy Violations

Low
Confidence
80% confidence
Finding
Natural-language policy checks apply to all file types. The document presents all user-facing instructions in Chinese and does not indicate that the skill is region-specific by design or provide an opt-in language/locale choice.

Static analysis

No suspicious patterns detected.