Back to skill

Security audit

stock sector hunter

Security checks for vulnerabilities and agentic risk

Overview

The skill is related to A-share stock screening, but it ships mismatched financial-analysis scripts and unsafe command/file/network patterns that users should review before installing.

Install only if you intentionally want a Chinese-language A-share market helper and are comfortable reviewing the scripts. The sector search behavior is not clearly separated from extra moving-average screeners, and the package should be fixed to avoid shell=True, avoid fixed /tmp output, use authenticated HTTPS market-data sources, and accurately document every shipped script before routine use.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/sector_hunter.py:20
Finding
Shell Command Injection Sink in Search Helper<![CDATA[ ## Vulnerability Details **File Location**: `scripts/sector_hunter.py`, lines 20-31 **Vulnerability Type**: Shell command injection **Risk Level**: Medium ### Vulnerable Code ```python script_path = "/root/.openclaw/workspace/skills/byted-web-search/scripts/web_search.py" cmd = f'python3 "{script_path}" "{query}" --count {count}' try: result = subprocess.run( cmd, shell=True, capture_output=True, text=True, timeout=30, cwd="/root/.openclaw/workspace/skills/byted-web-search" ) ``` ### Technical Analysis The `search()` function constructs a command string by interpolating `query` and `count`, then executes that string through a shell with `shell=True`. Quoting the query with double quotes does not prevent shell interpretation: command substitution and other shell constructs can still be evaluated inside double quotes. The current `main()` function generates the search query from fixed templates and an allowlisted sector keyword, which substantially limits direct exploitation through the documented command-line flow. Nevertheless, `search()` is a reusable function that accepts arbitrary arguments, and any future or external caller that passes attacker-controlled data can expose the command-injection sink. ### Attack Path 1. An attacker obtains influence over a value passed to `search()`, such as through a future API, plugin integration, or direct module invocation. 2. The attacker supplies shell syntax in `query` or `count`, such as command substitution. 3. The value is interpolated into the command string without shell-safe escaping. 4. `subprocess.run(..., shell=True)` passes the command to the system shell. 5. The shell evaluates the injected syntax and runs the attacker's command with the privileges of the Python process. The documented `main()` path does not currently pass the complete raw CLI query to `search()`, so exploitation requires another caller or a future code change that in ...[truncated 465 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Avoid invoking a shell. Pass each command argument separately: ```python result = subprocess.run( ["python3", script_path, query, "--count", str(count)], shell=False, capture_output=True, text=True, timeout=30, cwd="/root/.openclaw/workspace/skills/byted-web-search", check=False, ) ``` Additionally: - Validate that `count` is an integer within an expected range. - Keep sector selection restricted to an explicit allowlist. - Resolve and verify the search script path before execution. - Avoid exposing `search()` to arbitrary input unless callers enforce equivalent validation. - Run the Skill using a dedicated, least-privileged operating-system account. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ma_filter_fast.py:78
Finding
Predictable Temporary File Allows Symbolic-Link Overwrite<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ma_filter_fast.py`, lines 78-82 **Vulnerability Type**: Unsafe predictable temporary file **Risk Level**: Medium ### Vulnerable Code ```python # 保存到文件 with open('/tmp/ma_stocks.txt', 'w') as f: f.write(f"{len(results)}\n") for r in results: f.write(f"{r['code']},{r['close']},{r['ma5']},{r['ma10']}\n") ``` ### Technical Analysis The script writes to a fixed filename in the globally writable `/tmp` directory. Python's normal `open(..., 'w')` operation follows symbolic links and truncates an existing target. A local attacker can create `/tmp/ma_stocks.txt` as a symbolic link to another file before the script runs. If the process has permission to write to the linked target, the script will truncate and replace that target with stock-screening output. This is a time-of-check/time-of-use and unsafe temporary-file pattern. ### Attack Path 1. A local attacker predicts the fixed path `/tmp/ma_stocks.txt`. 2. Before the scanner runs, the attacker creates a symbolic link at that path pointing to a target file. 3. A user with greater file privileges runs `ma_filter_fast.py`. 4. `open('/tmp/ma_stocks.txt', 'w')` follows the symbolic link. 5. The linked target is truncated and overwritten with the generated result data. The target must be writable by the account running the scanner. Consequently, the most serious scenario occurs when the scanner runs under a privileged or service account. ### Impact Assessment Successful exploitation can corrupt or replace any file writable by the scanner account. This may cause denial of service, configuration corruption, or security-impacting modification if the account can overwrite sensitive configuration or application files. The issue does not independently grant permissions beyond those already held by the scanner process. Instead, it allows a less-privileged local attacker to redirect the process's existing write authority to an unintended tar ...[truncated 8 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Use the `tempfile` module to create a unique file securely: ```python import tempfile with tempfile.NamedTemporaryFile( mode="w", prefix="ma_stocks_", suffix=".txt", delete=False, encoding="utf-8", ) as f: f.write(f"{len(results)}\n") for r in results: f.write(f"{r['code']},{r['close']},{r['ma5']},{r['ma10']}\n") ``` If a stable output path is required: - Store the file in an application-owned directory that is not globally writable. - Set restrictive directory and file permissions. - Open the file using `os.open()` with `O_CREAT | O_EXCL | O_NOFOLLOW` where supported. - Verify ownership and file type before replacing an existing file. - Prefer an atomic write to a securely created temporary file followed by `os.replace()`. - Do not run the scanner with elevated privileges unless strictly necessary. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ma_filter_em.py:17
Finding
Market Data Retrieved over Unencrypted HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ma_filter_em.py`, lines 17-29 and 67-81 **Vulnerability Type**: Cleartext network communication **Risk Level**: Medium ### Vulnerable Code ```python # 东财API获取股票日线数据 url = f"http://push2his.eastmoney.com/api/qt/stock/kline/get" params = { "secid": f"{market}.{code}", "fields1": "f1,f2,f3,f4,f5,f6", "fields2": "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61", "klt": "101", # 日线 "fqt": "1", # 前复权 "beg": "20250501", "end": "20260630", "lmt": "20" # 只取最近20天 } resp = requests.get(url, params=params, timeout=5) ``` ```python # 使用东财的板块数据 url = "http://push2.eastmoney.com/api/qt/clist/get" params = { "pn": "1", "pz": "5000", "po": "1", "np": "1", "ut": "bd1d9ddb04089700cf9c27f6f7426281", "fltt": "2", "invt": "2", "fid": "f3", "fs": "m:0+t:6,m:0+t:13,m:1+t:2,m:1+t:23", "fields": "f12,f14" } resp = requests.get(url, params=params, timeout=10) ``` ### Technical Analysis Both the stock-list request and the historical-price request use plaintext HTTP. HTTP provides neither transport confidentiality nor authenticated response integrity. An attacker with a network interception position can observe requests or alter responses in transit. Because the returned JSON directly determines which securities are processed and whether they satisfy the moving-average criteria, modified responses can manipulate the scanner's financial output. The code also parses the response without calling `raise_for_status()` and performs limited structural validation, making malformed or substituted responses more likely to cause silent omissions or inaccurate results. ### Attack Path 1. A user executes `ma_filter_em.py` on a network controlled or observable by an attacker. 2. The script sends requests to the Eastmoney endpoints over plaintext HTTP. 3. The attacker intercepts the requests through a malicious access point, compromised router, proxy, DNS m ...[truncated 965 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Use provider-supported HTTPS endpoints and retain certificate verification: ```python url = "https://push2his.eastmoney.com/api/qt/stock/kline/get" resp = requests.get(url, params=params, timeout=5) resp.raise_for_status() ``` ```python url = "https://push2.eastmoney.com/api/qt/clist/get" resp = requests.get(url, params=params, timeout=10) resp.raise_for_status() ``` Further hardening should include: - Confirm that the provider officially supports the HTTPS endpoints before deployment. - Never disable TLS certificate verification. - Validate the response `Content-Type` and expected JSON schema. - Enforce strict formats for stock codes, dates, and numeric values. - Reject impossible or non-finite prices and unexpectedly large responses. - Handle JSON decoding and HTTP failures explicitly rather than silently suppressing exceptions. - Consider cross-checking financially significant data against an independent authenticated source. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (21)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says the skill discovers current strong A-share sectors and limit-up leading stocks, with code-prefix filtering and structured output by sector and leader. The supplied code does not analyze sectors,热点板块,涨停 behavior, leader stocks, or real-time searched market themes. Instead, it performs a technical scan over individual stocks using historical daily data and simple moving-average conditions (MA5 above MA10, both trending up). The only overlap is that it filters A-share codes by 00/60 prefixes, but that is incidental and insufficient to match the stated primary purpose. Therefore this is a clear description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
声明的核心能力是‘实时获取A股当日活跃板块、涨停龙头股’,重点对象是板块热度与龙头股;而代码完全没有进行板块排名、热度判断、涨停检测、龙头识别,也没有做联网搜索或输出板块维度结果。相反,它通过东方财富接口批量获取个股日线数据,使用MA5/MA10均线条件进行技术面选股。这属于与声明 materially different primary purpose 的情况,因此应判定为明显不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
声明描述的核心能力是“强势板块、热点板块、涨停龙头”的实时探测,这通常需要板块维度数据、涨停数据或市场热点信息。代码中并未获取或分析任何板块信息、涨停信息、龙头股关系或实时热门数据;相反,它对全部00/60开头股票逐只拉取历史日线,计算5日和10日均线,并筛选满足均线多头上行条件的个股。这属于技术指标选股工具,而非板块热点/涨停龙头探测器。虽然都与A股选股相关,且都涉及00/60前缀过滤,但主要目的和实际行为存在明显实质性不一致。

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The implementation materially diverges from the declared skill purpose: instead of identifying strong sectors and limit-up leader stocks, it performs a moving-average stock screen over individual A-shares. This kind of capability mismatch is dangerous because callers may trust the manifest and route requests or permissions based on the documented function, leading to misleading outputs, broken policy assumptions, or abuse of the skill under false pretenses.

Description-Behavior Mismatch

High
Confidence
98% confidence
Finding
The file’s actual behavior is a moving-average stock screener that scans all 00/60-prefixed equities and filters on MA5/MA10 conditions, which materially contradicts the declared skill purpose of finding strong sectors and limit-up leaders. In an agent setting, this kind of capability mismatch can cause the system to return misleading financial analysis under false pretenses, leading users or downstream automations to act on incorrect results.

Description-Behavior Mismatch

High
Confidence
97% confidence
Finding
The manifest describes a tool that searches for active A-share sectors and涨停龙头股, then outputs structured sector-plus-leader results with prefix filtering. This script instead performs a moving-average stock screen over all 00/60-prefixed stocks using historical daily price data, and never identifies sectors, hot themes, or limit-up leaders.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
cmd = f'python3 "{script_path}" "{query}" --count {count}'
    
    try:
        result = subprocess.run(
            cmd,
            shell=True,
            capture_output=True,
Confidence
99% confidence
Finding
This is a true command-injection risk: the tool invocation is assembled as a single shell string and executed with `shell=True`, allowing user-controlled query text to alter command structure. In the context of an agent skill, natural-language user input is especially attacker-controllable, making exploitation straightforward if an attacker can supply crafted arguments.

Lp3

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding
The skill advertises network access and a Python script but does not declare any explicit tool scope such as allowed-tools or permissions. That creates a least-privilege failure: a host may grant broader network, shell, or file capabilities than users or reviewers expect, increasing the blast radius if the script is modified, compromised, or behaves unexpectedly.

Vague Triggers

Medium
Confidence
95% confidence
Finding
Broad trigger phrases like '今日热门' or '热点板块' can cause accidental invocation in normal conversation, making the assistant perform unintended network searches or tool-assisted actions. In a skill with external search capability, overbroad activation increases the chance of unreviewed tool use, confusion, and cross-context execution.

Vague Triggers

Medium
Confidence
91% confidence
Finding
Ambiguous invocation examples reinforce loose activation behavior and make it harder for users and orchestrators to distinguish ordinary discussion from a command to run the skill. Because this skill depends on online search, unintended activation can lead to unnecessary external requests and misleading outputs presented as deliberate analysis.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The module docstring explicitly describes a moving-average stock picker, which contradicts the skill metadata advertising strong-sector and leader-stock discovery. This inconsistency is a security-relevant integrity issue because it indicates the artifact may have been repurposed, mispackaged, or swapped, making operator trust and downstream automation decisions unreliable.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The module docstring explicitly states this is a moving-average stock picker, directly conflicting with the skill’s published sector-hunting purpose. This inconsistency is dangerous because it signals specification drift and increases the chance that reviewers, orchestrators, or users will misunderstand what the code does, especially in a finance-related workflow where output semantics matter.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
All user-facing text in the module docstring and runtime output is in Chinese, and the file does not provide any language selection or explain that the tool is intentionally limited to a Chinese-speaking audience. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The module description and all user-facing behavior are written as Chinese-only, and the code later emits Chinese-only status/output strings. For an all-file-types natural-language policy check, this represents a locale/language constraint without user opt-in or documented regional justification.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The code invokes an external web search tool to send the constructed query off-box, but there is no explicit disclosure that user-provided query content will be transmitted to a network service. Although there is a debug print showing the search term, it does not warn about privacy or external data sharing.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
cmd = f'python3 "{script_path}" "{query}" --count {count}'
    
    try:
        result = subprocess.run(
            cmd,
            shell=True,
            capture_output=True,
Confidence
99% confidence
Finding
The code builds a shell command with untrusted input (`query`) and executes it with `subprocess.run(..., shell=True)`. Because `query` comes from CLI/user-controlled text, an attacker can inject shell metacharacters to execute arbitrary commands in the skill environment.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The manifest description and the rest of the file present the skill entirely in Chinese and imply a fixed-language interaction model, but they do not state that the skill is China-region-only or offer users a language option. Under the stated policy, forcing a specific language without opt-in is a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
This Python file contains its docstring and all user-facing print output in Chinese, with no option to select another language or statement that the skill is intentionally limited to a Chinese-language audience. Under the policy rule for natural-language constraints, forcing a specific language without user opt-in is a policy concern.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The module title and user-facing descriptions are presented exclusively in Chinese, and the script does not indicate that the user can choose another language or that the tool is intentionally limited to a Chinese-speaking context. This can violate language/locale policy where skills should not force a language without opt-in or justification.

Missing User Warnings

Low
Confidence
85% confidence
Finding
This Python code fetches stock data from an external source via akshare, which implies outbound network requests, but the script does not disclose this behavior to the user before or during execution. While the script prints progress and an investment disclaimer, it does not warn that it will contact remote data services and transmit query parameters such as stock symbols.

Description-Behavior Mismatch

Low
Confidence
77% confidence
Finding
The manifest focuses on producing structured板块+龙头个股列表 from real-time search results, but this script additionally persists scan results to /tmp/ma_stocks.txt. Local file output is not implied by the user-facing description of a sector/leader detector.

Static analysis

No suspicious patterns detected.