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

Content
View full analysis

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
View 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

Content
View full analysis

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
View 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.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
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.

Content

Scanner excerpt · SKILL.md (reported line 34)May include surrounding context.

  1. Configure Tushare Token:
    bash
    # Add to ~/.bashrc or ~/.bash_profile
    export TUSHARE_TOKEN="your_token_here"
    source ~/.bashrc
    

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

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

Medium
Category
Data Flow
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.

Content

Scanner excerpt · scripts/a_share_dcf.py (reported line 853)May include surrounding context.

python
# 写入文件
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}")

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/a_share_dcf.py (reported line 56)May include surrounding context.

python
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]

Intent-Code Divergence

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
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.

Content

No source excerpt is available for this finding.