Back to skill

Security audit

A-Share DCF Valuation

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to perform the advertised A-share DCF valuation, but its credential setup and dependency/report-writing practices need review before installation.

Install only after reviewing the dependency source and preferably using a dedicated virtual environment with pinned versions. Do not put the Tushare token in a global shell profile; use a temporary environment variable or secret manager, and avoid the documented verification command that expands the token into the process command line. Run the skill only for intended A-share tickers and check the generated report path before relying on the output.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:46
Finding
Tushare API Token Exposed Through Command-Line Expansion## Vulnerability Details **File Location**: `SKILL.md`, line 46 **Vulnerability Type**: Credential exposure through process arguments **Risk Level**: Medium ### Vulnerable Code ```bash python3 -c "import tushare as ts; ts.set_token('$TUSHARE_TOKEN'); pro = ts.pro_api(); print(pro.stock_basic(ts_code='600519.SH'))" ``` ### Technical Analysis The verification command places `$TUSHARE_TOKEN` inside a double-quoted shell argument. Before Python starts, the shell expands this variable and embeds the actual token in the `python3 -c` command-line argument. Consequently, the credential may be visible through: - Process inspection tools while the command is running. - Process accounting or endpoint-monitoring systems. - Shell tracing, debugging, or command-execution telemetry. - Logs produced by wrappers that record complete argument vectors. This exposure is unnecessary because the main implementation already uses the safer pattern at `scripts/a_share_dcf.py:34`, where Python reads the token directly from the environment. ### Attack Path 1. A user exports a valid `TUSHARE_TOKEN` and runs the documented verification command. 2. The shell substitutes the token into the argument passed to `python3`. 3. A local process observer, monitoring agent, or command-logging wrapper records the expanded argument. 4. An attacker with access to that data extracts the token. 5. The attacker uses the token against Tushare APIs within the permissions and quota associated with the affected account. ### Impact Assessment Successful exploitation exposes the user's Tushare API credential. The attacker could consume the account's API quota, access data available under the account's Tushare permissions, and potentially cause service disruption or account-level abuse. This issue does not directly grant operating-system privilege escalation. Its scope is limited to the affected Tushare account and the capabilities assigned to the leaked ...[truncated 7 chars]
Remediation
## Remediation Suggestions Read the token from the environment inside Python so that its value is not embedded in the command-line argument: ```bash python3 -c "import os, tushare as ts; ts.set_token(os.environ['TUSHARE_TOKEN']); pro = ts.pro_api(); print(pro.stock_basic(ts_code='600519.SH'))" ``` Additional hardening measures: 1. Recommend storing the token in a dedicated secret manager or a permission-restricted environment configuration rather than a globally sourced shell profile. 2. Warn users not to enable shell tracing while configuring or testing credentials. 3. Avoid printing, logging, or including the token in exception messages. 4. Revoke and rotate any token that may already have been exposed through process or telemetry logs.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:41
Finding
Unpinned Third-Party Dependencies Installed from a Mutable Package Index## Vulnerability Details **File Location**: `SKILL.md`, lines 24-28 and 41 **Vulnerability Type**: Uncontrolled third-party dependency resolution **Risk Level**: Medium ### Vulnerable Code The dependency documentation explicitly permits the latest Tushare release and broad minimum versions: ```markdown | Package | Version | Purpose | |---------|---------|--------| | `tushare` | Latest | A-share financial data API | | `pandas` | ≥1.0 | Data processing | | `numpy` | ≥1.18 | Numerical calculations | | `scipy` | ≥1.4 | Beta regression (stats module) | ``` The installation command resolves these packages without a lock file or artifact hashes: ```bash pip install tushare pandas numpy scipy ``` ### Technical Analysis The installation instructions retrieve mutable package versions from whichever pip index is active in the user's environment. No exact versions, hashes, lock file, or explicit trusted index are specified. This creates a supply-chain risk because the code reviewed during the Skill audit may not be the code later installed. A compromised upstream release, malicious package served by a configured mirror, or unsafe index configuration could introduce arbitrary behavior. It also makes builds non-reproducible and increases the risk of unexpected compatibility or security regressions. The declared functionality requires these numerical and API libraries, but it does not require installing uncontrolled future versions. Therefore, the dependency privileges exceed the minimum assurance necessary for reproducible execution. ### Attack Path 1. A user follows the documented `pip install` command. 2. Pip queries the environment's configured package index or mirror. 3. Pip selects the newest compatible artifacts because no exact versions or hashes are enforced. 4. A compromised upstream release or malicious artifact from an untrusted index is downloaded and installed. 5. Malicious package code executes du ...[truncated 775 chars]
Remediation
## Remediation Suggestions 1. Pin every direct and transitive dependency to reviewed versions in a lock file. 2. Require artifact hashes, for example through a hash-locked `requirements.txt` installed with: ```bash python3 -m pip install --require-hashes -r requirements.txt ``` 3. Generate and review the lock file using a dependency-management tool such as `pip-tools`. 4. Explicitly configure a trusted package index and avoid untrusted or implicit extra indexes. 5. Install dependencies in a dedicated virtual environment rather than the system Python environment: ```bash python3 -m venv .venv . .venv/bin/activate python3 -m pip install --require-hashes -r requirements.txt ``` 6. Run dependency vulnerability and provenance checks during release preparation. 7. Do not install or execute the Skill as root unless strictly required; this Skill does not require administrative privileges.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The documented behavior exceeds the declared purpose by requiring external API/network access and local file writes without declaring those capabilities, and it also references likely undefined variables in fallback/reporting paths. This combination is dangerous because users may authorize a seemingly simple valuation skill that actually performs broader side effects, while the code defects can trigger crashes or inconsistent outputs that undermine safe operation and error handling.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill instructs use of environment variables and writes reports to the workspace, but it does not declare any explicit tool scope or permissions. This creates a trust and containment gap: a runner may permit network, environment, or file operations implicitly, making it harder for users and policy engines to understand or restrict what the skill can do.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The description explicitly states the skill will 'output complete Markdown report (in Chinese),' which forces a specific language. Under the policy, locale or language constraints should either be optional for the user or clearly justified as region-specific; this file does not provide such opt-in or justification.

Session Persistence

Medium
Category
Rogue Agent
Content
1. **Configure Tushare Token**:
   ```bash
   # Add to ~/.bashrc or ~/.bash_profile
   export TUSHARE_TOKEN="your_token_here"
   source ~/.bashrc
   ```
Confidence
90% confidence
Finding
The setup instructions tell users to persist the Tushare token in ~/.bashrc or ~/.bash_profile, which stores a long-lived secret in shell startup files. This increases exposure through accidental disclosure, overbroad reuse across sessions, and inheritance by unrelated shells or tools, especially on shared systems or where dotfiles are backed up or inspected.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The section header states 'Report Structure (Markdown, output in Chinese),' which is a natural-language instruction to always produce Chinese output. This is a language policy constraint and no alternative language path or user choice is described nearby.

Natural-Language Policy Violations

Medium
Confidence
85% confidence
Finding
The module docstring and user-facing output strings are consistently Chinese, with no option for the user to select another language. The policy requires avoiding forced language or locale constraints unless the skill offers user choice or clearly documents a justified region-specific limitation.

Intent-Code Divergence

Medium
Confidence
88% confidence
Finding
The report text at L736 states Beta is based on a regression against HS300 and interpolates `r2`, but `r2` is only assigned inside the successful regression branch at L142. If the data is insufficient or an exception occurs at L148-L151, Beta falls back to 1.2 and `r2` is never set, so the documentation of the result contradicts the actual execution path.

Tainted flow: 'report_path' from os.getenv (line 852, credential/environment) → open (file write)

Medium
Category
Data Flow
Content
# 写入文件
os.makedirs(REPORTS_DIR, exist_ok=True)
report_path = os.path.join(REPORTS_DIR, f'dcf_{COMPANY_NAME}_{TODAY}.md')
with open(report_path, 'w', encoding='utf-8') as f:
    f.write(report)

print(f"\n  报告已保存: {report_path}")
Confidence
85% confidence
Finding
The output path is derived from OPENCLAW_WORKSPACE and the filename incorporates the user-supplied COMPANY_NAME, then written with open() without validation or normalization. An attacker who controls the environment variable or passes path-separator sequences in COMPANY_NAME could cause the script to write the report outside the intended reports directory, potentially overwriting arbitrary files accessible to the process.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Content
def get_annual(pro_api, api_name, ts_code, fields, start_year=2018):
    """获取年报数据,去重并按时间升序排列"""
    try:
        df = getattr(pro_api, api_name)(ts_code=ts_code, fields=fields)
        df['end_date'] = pd.to_datetime(df['end_date'])
        df = df[df['end_date'].dt.month == 12]
        df = df[df['end_date'].dt.year >= start_year]
Confidence
50% confidence
Finding
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Intent-Code Divergence

Low
Confidence
92% confidence
Finding
The report's key assumptions say 'FCFF 计算:经营现金流净额 - 资本开支', yet the implementation prefers `fcff_direct` from `fina_indicator` whenever available at L182-L185. That is an active mismatch between the report's described method and the code's actual method selection.

Missing User Warnings

Low
Confidence
90% confidence
Finding
This code creates the reports directory and writes a report file into the workspace, which is a file-writing operation covered by the missing-warning rule for code files. Although the script prints the saved path after writing, there is no prior user-facing warning, confirmation, or docstring/comment disclosing that execution will create files under the workspace.

Static analysis

No suspicious patterns detected.