Back to skill

Security audit

query and monitor stock

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent stock quote and alert tool, but it should be reviewed because its background monitor can kill an unchecked PID and persists messaging and session data locally.

Review before installing. Use it only if you are comfortable with a persistent local stock monitor, outbound OpenClaw alert messages, local storage of watchlists/recipient IDs/cookies, and the current unsafe PID-based stop behavior. Prefer fixing PID validation, dependency pinning, and explicit confirmation for watchlist clearing and monitor start/stop before broad deployment.

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
monitor.py:130
Finding

Untrusted PID File Can Cause Termination of an Unrelated Process

Content
View full analysis

Vulnerability Details

File Location: monitor.py:130-131
Vulnerability Type: Unvalidated process identifier used for process termination
Risk Level: High

Vulnerable Code:

python
pid = int(_PID_PATH.read_text(encoding="utf-8").strip())
os.kill(pid, signal.SIGKILL)

Technical Analysis

stop_monitor() reads a process identifier directly from the project-local data/monitor.pid file and sends an unconditional SIGKILL to that process. The implementation does not verify that:

  • The PID belongs to a monitor process started by this application.
  • The process executable is the expected Python interpreter.
  • The process command line references monitor.py.
  • The process creation time matches the monitor instance that created the PID file.
  • The PID has not been reused by the operating system after the original monitor exited.

Because PID files are ordinary filesystem objects and no restrictive permissions or ownership validation are applied, any local actor or compromised component capable of writing to the project directory can replace the stored PID. A stale PID may also be reassigned naturally by the operating system.

The use of SIGKILL increases the impact because the selected process cannot perform cleanup, flush pending data, or reject the termination request.

Attack Path

  1. A local attacker or compromised process obtains write access to data/monitor.pid.
  2. The attacker identifies the PID of another process running under the same operating-system account.
  3. The attacker replaces the contents of data/monitor.pid with that PID.
  4. The user or Agent invokes stop_monitor() or restart_monitor() through the documented interface.
  5. The application reads the attacker-controlled PID and calls os.kill(pid, signal.SIGKILL).
  6. The unrelated process is immediately terminated.

A similar outcome can occur without an active attacker if the monitor exits without removin ...[truncated 506 chars]

Remediation
View remediation

Remediation Suggestions

  • Store more than a bare PID. Record the PID, process creation time, and a cryptographically random instance identifier.
  • Before signaling, verify that the process creation time still matches the recorded value and that its executable and command line correspond to this project's monitor.py.
  • Prefer cooperative shutdown through an authenticated local IPC mechanism, process handle, event, pipe, or owner-restricted control socket.
  • Send SIGTERM first and wait for a bounded period before considering forced termination.
  • Create the runtime data directory and PID file with owner-only permissions, such as mode 0700 for the directory and 0600 for the file where supported.
  • Use an atomic, exclusively acquired lock file to prevent multiple monitor instances and stale-state races.
  • If process identity cannot be conclusively verified, refuse to send a signal and report that the PID file is stale or invalid.

T09 · Insecure Skill Coding Practices

Warning
Location
monitor.py:289
Finding

Monitoring Recipient Identifier Is Exposed in Process Arguments

Content
View full analysis

Vulnerability Details

File Location: monitor.py:289-301
Vulnerability Type: Sensitive identifier disclosure through command-line arguments
Risk Level: Medium

Vulnerable Code:

python
cmd = [
    sys.executable,
    str(Path(__file__).resolve()),
    "--interval", str(interval),
    "--threshold", str(threshold),
    "--target", target,
    "--log", str(log_path),
]

if sys.platform == "win32":
    proc = subprocess.Popen(cmd, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
else:
    proc = subprocess.Popen(cmd, start_new_session=True)

Technical Analysis

The persistent OpenClaw message recipient identifier is passed to the detached monitor through the --target command-line argument. Process command lines can be exposed through operating-system process listings, diagnostic utilities, endpoint monitoring software, crash reports, or process telemetry. Visibility to other users depends on the host operating system and its process isolation configuration.

Passing arguments as a list correctly avoids shell-command injection, but it does not protect the confidentiality of those arguments. The target remains present in the child process command line for the monitor's entire lifetime.

The same identifier is also persisted in data/config.json; however, the command-line exposure broadens its visibility beyond components with direct access to that file.

Attack Path

  1. A user starts monitoring with a configured OpenClaw target.
  2. start_monitor() includes that target in the detached process argument list.
  3. A local user, monitoring agent, diagnostic process, or compromised component enumerates running process command lines.
  4. The observer recovers the recipient identifier from the --target argument.
  5. The identifier may then be used for user correlation, targeted messaging attempts, or unauthorized routing where other controls permit it.

Impact Assessment

...[truncated 398 chars]

Remediation
View remediation

Remediation Suggestions

  • Do not include the target identifier in child-process command-line arguments.
  • Have the monitor read the target from an owner-restricted configuration file after startup, or transmit it through a protected local IPC channel.
  • Apply owner-only permissions to data/config.json, such as mode 0600 where supported.
  • Avoid printing or logging the complete recipient identifier; redact most of the value when diagnostic output is necessary.
  • Document the sensitivity and retention behavior of the target identifier.
  • On platforms supporting inherited file descriptors, pass protected configuration through an inherited pipe rather than the process argument list or environment.

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Open-Ended Dependency Versions Create a Non-Reproducible Supply Chain

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-3
Vulnerability Type: Unpinned third-party dependencies without integrity hashes
Risk Level: Medium

Vulnerable Code:

text
akshare>=1.10.0
pandas>=1.5.0
requests>=2.28.0

Technical Analysis

Every direct dependency uses an open-ended minimum version. The project provides no lock file, upper bounds, exact reviewed versions, or package hashes. Consequently, the documented installation command can resolve to versions that did not exist when the Skill was audited, along with an uncontrolled set of transitive dependencies.

No typographical package-name issue or known malicious direct dependency was identified in the reviewed files. The weakness is that package selection and integrity are delegated entirely to the package index and resolver at installation time. This prevents reproducible builds and increases exposure to compromised releases, compromised package indexes, dependency confusion in misconfigured environments, and unexpected security regressions in future versions.

Python package installation may execute build backends or other packaging logic. Imported dependencies also execute code under the privileges of the user running the Skill.

Attack Path

  1. A user follows the documented installation procedure using pip install -r requirements.txt.
  2. Pip queries the configured package index and selects any available versions satisfying the minimum constraints.
  3. A compromised index, malicious future release, or manipulated package-resolution environment supplies an unsafe direct or transitive dependency.
  4. The package executes code during installation, import, or normal runtime.
  5. That code operates with the privileges and filesystem/network access of the user running the installation or Skill.

Impact Assessment

Successful supply-chain compromise could result in arbitrary code execution under the installing or runtim ...[truncated 391 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin every direct dependency to an exact reviewed version.
  • Generate and commit a lock file that resolves all transitive dependencies.
  • Record cryptographic hashes for all installation artifacts and install with pip's --require-hashes option.
  • Use a trusted, explicitly configured package index and disable unintended extra indexes.
  • Review dependency updates before changing the lock file and run vulnerability scanning in continuous integration.
  • Prefer prebuilt, verified wheels where practical to reduce exposure to arbitrary build-time execution.
  • Periodically update pinned versions through a controlled process rather than leaving versions permanently outdated.
Vulnerability Patterns
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

从提供的代码看,这只是包级导出层,将查询与搜索相关函数从子模块中重新导出。能直接支持的能力包括按代码/名称获取股票详情、按名称搜索股票、获取股票列表。声明中提到的“管理自选股”和“启动股票价格监控/提醒”在该代码片段中没有任何体现,也没有导出相关接口。因此,代码实际行为仅覆盖了声明中的一部分,声明范围明显大于当前代码所呈现的能力,构成描述与行为不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

代码的核心功能与声明中的“查询A股实时行情、支持股票代码/名称关键字”部分基本一致:可输入6位代码或名称关键字,搜索匹配股票并输出详细行情。因此查询能力是匹配的。但声明还包含一组重要能力:管理自选股、清空自选股、启动股票价格监控、价格提醒等;在提供的代码中完全没有相关数据结构、持久化逻辑、监控循环、定时任务、阈值设置或提醒发送实现。相反,代码是一个本地CLI工具,只提供单次查询、交互选择匹配股票,以及查看缓存状态的辅助命令。由于声明涵盖了多项用户可触发的核心功能,而代码并未实现这些功能,这属于描述与实际行为的明显不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

从代码看,核心功能是实时行情查询:get_detail 按6位代码查行情,get_detail_by_name 按名称关键字检索后查行情,返回最新价、涨跌幅、成交额等字段。这与声明中的“查询A股实时行情”部分一致,也支持代码和名称关键字。 但声明还包含多项重要能力:自选股管理(添加/删除/查看/清空)以及价格监控、盯盘、提醒等,代码中完全没有这些实现。因此,代码实际行为只覆盖了声明中的一小部分,属于描述范围明显大于实际能力的情况。 另外,代码会访问雪球首页和雪球 JSON API,并将cookie/token缓存到本地文件,这些属于实现细节,本身不一定构成问题,但也说明实际代码依赖的外部资源与状态管理比声明更具体。综合判断,声明不能准确代表该代码块的实际功能,存在明显不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

声明描述的是一个较完整的股票助手,覆盖行情查询、自选股管理和监控提醒等多种交互能力;但提供的代码片段只展示了调用 start_monitor 启动监控,且监控标的是预设的两只股票,参数也是固定的。虽然“启动股票价格监控”与声明的一部分相符,但从该代码实际行为看,其主要能力远比声明狭窄,且没有体现根据用户请求查询行情或管理自选股的功能,因此描述不能准确代表该代码块的实际行为。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

声明描述的是一个综合股票技能,包含三类核心能力:实时行情查询、自选股管理、启动价格监控/提醒。实际代码片段只涉及自选股管理文件读写,并在增删清操作结果中附带一个来自 monitor.is_running() 的监控状态文本。它没有执行实时行情查询逻辑(虽然 add 中调用了 get_detail / get_detail_by_name 来解析股票信息,但用途是确定代码和名称,不是向用户提供行情、涨跌或股价结果),也没有启动、配置或管理监控提醒功能。因此,代码行为只覆盖声明中的一部分,且缺失两个重要已声明能力,构成描述与实际行为不一致。

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README explicitly states at L121 and L196 that add/remove/clear operations will not automatically start or stop the monitor and only return monitor_status for the caller to act on. However, the module description at L027 says watchlist.py handles watchlist changes while '联动监控进程', which implies automatic coordination with the monitoring process. These statements are in tension and actively describe different operational intent.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill exposes shell, file read/write, and network-capable behavior through inline Python commands, but it does not declare any tool scope or permission boundaries. This makes the effective capability surface much broader than what a host or reviewer can evaluate up front, increasing the risk of unintended command execution, local file modification, and outbound communication.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill advertises broad trigger phrases like stock price, market, monitoring, and reminders that overlap with normal finance conversation. In an agent environment, overly broad activation can cause the skill to run in situations where the user did not intend persistent state changes, shell-backed operations, or outbound monitoring setup.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill stores a persistent notification target in a local config file and later uses it for outbound push messages, but the instructions do not require an explicit user warning or confirmation about persistence and message delivery effects. This can lead to unintended long-lived notification routing, privacy issues, or alerts being sent to the wrong recipient if the target is mis-set or inherited from prior state.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code contains user-facing natural-language documentation entirely in Chinese, and there is no indication that the skill offers a language choice or that the locale restriction is intentionally limited to a Chinese-specific context. The policy requires flagging language or locale constraints when they are imposed without user opt-in or clear justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code presents its purpose and operational messaging entirely in Chinese, beginning with the module docstring, and the rest of the user-visible strings follow the same pattern. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified.

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

python
f"当前价 {price:.3f} 元(上次 {prev:.3f} 元)|"
        f"今开 {open_price:.3f} 元,距开盘 {from_open_pct:+.2f}%"
    )
    subprocess.run(
        ["openclaw", "message", "send", "--target", target, "--message", msg],
        check=False,
    )

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest says the skill monitors stock prices and sends reminders, but the code implements this by executing the external openclaw command via subprocess.run. Using external process execution is a broader capability than the stated stock-domain purpose and is not explicitly disclosed in the manifest.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The manifest describes querying A-share prices, managing a watchlist, and starting monitoring, but this implementation also launches a detached subprocess, persists its PID, and later kills it. Background process lifecycle management is a host-control capability that is not clearly justified by the narrow stock-assistant purpose as stated.

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

python
]

    if sys.platform == "win32":
        proc = subprocess.Popen(cmd, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
    else:
        proc = subprocess.Popen(cmd, start_new_session=True)

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

python
if sys.platform == "win32":
        proc = subprocess.Popen(cmd, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
    else:
        proc = subprocess.Popen(cmd, start_new_session=True)

    _DATA_DIR.mkdir(parents=True, exist_ok=True)
    _PID_PATH.write_text(str(proc.pid), encoding="utf-8")

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The argparse description and help strings are all written in Chinese, which imposes a specific language on users of the CLI. Because the file does not offer a language choice or explain that the tool is intentionally region-specific, this conflicts with the language/locale policy.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · quote.py (reported line 11)May include surrounding context.

python
from market import add_prefix, strip_prefix
from search import search_by_name

_HERE = __import__("pathlib").Path(__file__).parent
_DATA_DIR = _HERE / "data"
_TOKEN_CACHE_PATH = _DATA_DIR / "xueqiu_token.json"
_TOKEN_TTL = 6 * 3600   # token 有效期:6 小时

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The code persists session cookies obtained from xueqiu.com to a local JSON file in cleartext for six hours. If the host is multi-user, the filesystem is exposed, or logs/backups capture the file, another local actor could reuse the cookies to impersonate the session against the upstream service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The module docstring is written entirely in Chinese and the public API documentation and returned status strings in this file also assume Chinese as the required language. Under the policy, forcing a specific language without opt-in or documented regional justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This markdown file documents configuring a user OpenID-like identifier (user:ou_xxxx) and sending alert messages via openclaw message send, which transmits monitoring content externally. While the behavior is described functionally, there is no explicit user-facing warning that stock watchlist activity and alert content will be sent to an external messaging target and that the target identifier is stored in data/config.json.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

Watchlist add/remove/clear operations persist changes to a local file, but the operational instructions do not consistently foreground that these changes are durable beyond the current interaction. In an agent context, silent persistence increases the chance of surprising state retention, accidental portfolio tracking, or later monitoring actions operating on stale user data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The natural-language text in the module docstring is written only in Chinese ('stock 包公开 API') with no indication of language choice, opt-in, or region-specific justification. Under the stated policy, forcing a specific language without user opt-in can be a locale/language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The user-facing docstring, prompts, and output strings are entirely in Chinese, including the CLI description and all interaction messages. The policy allows locale constraints only when the skill offers language choice or clearly documents a justified region-specific limitation, which is not stated here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

Natural-language strings and documentation in this file are exclusively Chinese, which effectively forces a specific language without indicating user opt-in or a justified locale restriction. Under the stated policy, language constraints should be optional or clearly documented as region-specific.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.