Back to skill

Security audit

Baostock Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill has a clear stock-data purpose, but ordinary queries can run unsafe local commands and request broad workspace file access.

Do not install this version unless you are prepared to review and contain it. A safer release should run only packaged code, replace shell exec with argument-array process execution and strict input validation, remove workspace-wide filesystem permissions, restrict file export paths, pin dependencies, and align the manifest with the actual entry points.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
index.ts:18
Finding

OS Command Injection Through Unvalidated Skill Input

Content
View full analysis
{ const { exec } = require("child_process"); exec(`"${scriptPath}" ${args}`, { maxBuffer: 1024 * 1024 }, (error, stdout, stderr) => { if (error) { reject(new Error(stderr || error.message)); return; } try { const result = JSON.parse(stdout); ``` ### Technical Analysis The skill obtains `symbol`, `type`, `start_date`, `end_date`, and `frequency` from its input and interpolates them directly into a command string. It then passes that string to `child_process.exec()`, which executes commands through a system shell. No shell escaping, quoting, schema validation, or strict allowlist is applied before constructing the command. Consequently, shell metacharacters contained in any input field can terminate or alter the intended command and append an arbitrary command. Although the Python CLI defines `argparse` choices for some arguments, those checks occur only after shell interpretation. They therefore cannot prevent command injection in the TypeScript entry point. ### Attack Path 1. An attacker supplies a crafted field such as a symbol containing shell syntax, for example a separator followed by an operating-system command. 2. The value is interpolated into the `args` string without escaping. 3. The full string is supplied to `exec()`. 4. The system shell parses both the i ...[truncated 663 chars]
Remediation
View remediation

T07 · Tool Hijacking and Spoofing

Error
Location
index.ts:29
Finding

Execution of an Unpackaged and Unaudited External Tool

Content
View full analysis
{ const { exec } = require("child_process"); exec(`"${scriptPath}" ${args}`, { maxBuffer: 1024 * 1024 }, (error, stdout, stderr) => { ``` ### Technical Analysis The TypeScript entry point does not execute the reviewed `scripts/baostock_cli.py` file included in the project. Instead, it invokes a hard-coded absolute path under another user's mutable OpenClaw workspace. The referenced `baostock` executable is not present in the supplied project. Its implementation and integrity therefore cannot be established from the audited artifact. If another process or user can create or replace the file at that location, normal skill calls will execute the replacement under the identity of the OpenClaw process. This also makes the package non-portable and creates a discrepancy between the reviewed source code and the code actually executed at runtime. ### Attack Path 1. An attacker gains write access to `/Users/nico/.openclaw/workspace/skills/baostock-skill/baostock`, or causes a malicious file to be placed there during deployment. 2. The user invokes the BaoStock skill for an ordinary market-data request. 3. `index.ts` executes the external file instead of the packaged Python implementation. 4. The substituted executable runs attacker-controlled logic with the OpenClaw process privileges. ### Impact Assessment The external executable receives the same execution privileges as the skill host. A successful replacement can run arbitrary code, read or modify accessible workspace files, return spoofed financial data, or misuse any environment-level authority available to OpenClaw. The exact exploitability depends on who can write to the hard-coded path, but the package p ...[truncated 55 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
skill.json:25
Finding

Workspace-Wide Filesystem Permissions Violate Least Privilege

Content
View full analysis
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
skill.json:14
Finding

Unpinned Third-Party Python Dependencies

Content
View full analysis
=0.8.8", "pandas": ">=1.0" }, "requirements": [ "baostock", "pandas", "numpy" ], ``` The accompanying installation instructions in `SKILL.md`, lines 51-58, also install an unpinned package: ```bash pip3 install baostock ``` ### Technical Analysis The dependency declarations use open-ended minimum versions, while the `requirements` list and installation command omit versions entirely. No lockfile, package hashes, upper bounds, or trusted-index restrictions are provided. As a result, installation may retrieve dependency releases that were not reviewed with this skill. Future incompatible or compromised releases could change runtime behavior or execute unwanted code during installation or import. No evidence was found that the currently named packages are intentionally malicious. The issue is the absence of reproducible and integrity-protected dependency resolution. ### Attack Path 1. A user or deployment system installs the dependencies according to the manifest or documentation. 2. The package manager selects the newest release satisfying the open-ended constraint. 3. A compromised, malicious, or unexpectedly incompatible release is downloaded. 4. Package installation hooks or imported package code executes in the deployment environment. 5. The dependency gains the privileges of the installer or skill process. ### Impact Assessment The impact depends on the selected package release and installation privileges. A compromised dependency could execute code, access environment data, alter installed files, or compromise the runtime. Open-ended version ranges also create availability and integrity risks through unreviewed breaking changes. ]]>
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
skill.json:8
Finding

Manifest References Nonexistent Entry Points and Scripts

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • 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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The code generally aligns with the broad domain of querying Chinese A-share market data via BaoStock, especially for quotes and historical K-line data. However, the description overstates capabilities: there is no implementation for fundamentals or financial reports, and the so-called quote function fetches the latest available daily bar from historical data rather than a true real-time quote feed. The code also adds a stock-list capability and index-history support not explicitly called out in the description. The main mismatch is that several prominently declared data types are not actually implemented.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill builds a shell command from user-controlled fields and invokes it via child_process.exec, even though the skill is presented as a simple market-data query tool. This creates a command-injection path because values like symbol, type, or frequency are interpolated directly into a shell command string, allowing arbitrary local command execution if an attacker can influence input.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill silently launches a local binary without any disclosure to the user, expanding its capabilities beyond what a user would reasonably expect from a data-query skill. In this file, that hidden subprocess behavior is especially risky because it is paired with unsanitized shell command construction, making the lack of disclosure part of a broader unsafe execution design.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The CLI allows writing fetched market data to any filesystem path supplied by the caller via --output, which exceeds the described market-query behavior and creates an arbitrary file-write primitive. In an agent context, a user or prompt-influenced caller could direct output into sensitive locations, overwrite existing files, or plant data where other processes may consume it.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The description says to use the skill when the user asks for stock quotes, historical data, fundamentals, or market analysis, which is a broad natural-language scope rather than a constrained trigger list. While the domain is finance-specific, the activation boundary is still ambiguous because it does not clarify exclusions or negative examples for when this skill should not be invoked.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The manifest frames this as a BaoStock market-data query skill for quotes, history, fundamentals, and analysis. The example --output stocks.csv introduces a file-writing/export capability, which is not justified by the stated purpose of querying market data and is a broader operational capability than the manifest describes.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The code writes to a user-specified path without any confirmation, warning, or policy check, so the first visible disclosure is the write itself. While this is largely a UX/policy issue, in an autonomous skill it increases the chance of unexpected local side effects and makes abuse of the file-write behavior easier.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The description field is entirely Chinese-language text and does not indicate that the skill supports multiple languages or that Chinese is an intentional, user-selected locale. Under the policy for natural-language issues, forcing a specific language without opt-in can be a locale-policy concern.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
index.ts:32