Back to skill

Security audit

investment-data

Security checks for vulnerabilities and agentic risk

Overview

This skill should be reviewed before install because it claims to provide real investment data but its core queries return placeholder data and its downloader handles remote archives unsafely.

Review this skill carefully before installing. Do not rely on its query output for investment analysis unless the data retrieval code is fixed to read verified real datasets and clearly label provenance. Avoid running the downloader or auto-update workflows until archive integrity checks and safe extraction are added, and run any data download under a least-privileged account with a controlled output directory.

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
scripts/download_data.py:62
Finding

Unsafe Extraction of an Untrusted Tar Archive

Content
View full analysis

Vulnerability Details

File Location: scripts/download_data.py, lines 62-71
Vulnerability Type: Path traversal and arbitrary file overwrite through unsafe archive extraction
Risk Level: High

Vulnerable Code

python
def extract_tar(tar_path: str, output_dir: str) -> bool:
    """解压 tar.gz 文件"""
    try:
        logger.info(f"正在解压: {tar_path}")
        with tarfile.open(tar_path, 'r:gz') as tar:
            tar.extractall(path=output_dir)
        logger.info(f"解压完成: {output_dir}")
        return True
    except Exception as e:
        logger.error(f"解压失败: {e}")
        return False

Technical Analysis

tar.extractall() is invoked on a remotely downloaded archive without validating archive member names or link targets. Depending on the Python runtime and extraction behavior, malicious entries containing absolute paths, ../ traversal components, symbolic links, hard links, or special files may escape the intended extraction directory.

The archive comes from an external GitHub release and is not authenticated independently. Consequently, compromise of the upstream repository, its release publishing credentials, or the release asset could expose users to a crafted archive.

Attack Path

  1. An attacker gains control over, or otherwise compromises, the upstream release asset.
  2. The attacker creates qlib_bin.tar.gz with a member such as ../../.bashrc, or with a link that redirects a later archive member outside the destination.
  3. A user runs python scripts/download_data.py --latest or invokes InvestmentData.update_data().
  4. The Skill downloads the malicious archive into the data directory.
  5. tar.extractall(path=output_dir) processes the malicious member without application-level validation.
  6. Files outside output_dir may be created or overwritten with the privileges of the user running the Skill.
  7. If a startup file, imported Python module, executable, or security-sensitive configuration is overwritten, attacker- ...[truncated 761 chars]
Remediation
View remediation

Remediation Suggestions

  1. Validate every archive member before extraction:

    • Reject absolute paths.
    • Reject paths containing traversal components.
    • Resolve the destination and verify it remains beneath the resolved extraction root.
    • Reject device files and other special entries.
    • Reject symbolic and hard links, or validate their resolved targets rigorously.
  2. On supported Python versions, use the restrictive data extraction filter:

python
with tarfile.open(tar_path, "r:gz") as tar:
    tar.extractall(path=output_dir, filter="data")
  1. Do not rely exclusively on the runtime filter. Add explicit containment checks for compatibility and defense in depth.

  2. Extract into a newly created temporary directory rather than directly into the live data directory. Move validated files into place only after successful verification.

  3. Verify the archive's checksum or signature before opening it.

  4. Run the downloader with a dedicated, least-privileged account and never as an administrator or root user.

T08 · Insecure Dependencies

Warning
Location
scripts/download_data.py:21
Finding

Remote Dataset Accepted Without Integrity or Authenticity Verification

Content
View full analysis

Vulnerability Details

File Location: scripts/download_data.py, lines 21-27 and 113-126
Vulnerability Type: Unverified remote release asset and mutable upstream dependency
Risk Level: Medium

Vulnerable Code

python
def get_latest_release() -> str:
    """获取最新 release 版本"""
    url = "https://api.github.com/repos/chenditc/investment_data/releases/latest"
    resp = requests.get(url)
    resp.raise_for_status()
    data = resp.json()
    return data['tag_name']
python
# 下载 URL
tar_filename = "qlib_bin.tar.gz"
download_url = f"https://github.com/chenditc/investment_data/releases/download/{version}/{tar_filename}"

# 临时文件路径
temp_tar = output_dir / tar_filename

# 下载
if not download_file(download_url, temp_tar):
    sys.exit(1)

Technical Analysis

The downloader automatically resolves the latest release and trusts the associated archive solely because it is delivered over HTTPS. The Skill does not pin a reviewed release, compare a cryptographic digest, or verify a publisher signature.

TLS protects the transport connection but does not establish that a release asset is the exact artifact reviewed or intended by the Skill author. If the upstream repository or release-publishing credentials are compromised, an attacker can replace or publish an altered archive that the Skill will accept automatically.

The risk is amplified by the unsafe archive extraction in extract_tar(), although integrity failure alone can also silently corrupt financial datasets.

Attack Path

  1. An attacker compromises the upstream GitHub repository, a maintainer account, release automation, or release asset publishing process.
  2. The attacker publishes a new release or replaces qlib_bin.tar.gz.
  3. A user invokes the downloader with --latest, directly or through InvestmentData.update_data().
  4. The Skill queries the upstream API and obtains the attacker-controlled latest tag.
  5. The archive is downloaded over HTTPS but no expected digest or sig ...[truncated 907 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin a reviewed dataset release rather than resolving an unrestricted latest release by default.

  2. Distribute an expected SHA-256 or stronger digest through a trusted channel and verify it before extraction:

python
import hashlib

def sha256_file(path):
    digest = hashlib.sha256()
    with open(path, "rb") as source:
        for chunk in iter(lambda: source.read(1024 * 1024), b""):
            digest.update(chunk)
    return digest.hexdigest()
  1. Fail closed if the digest does not exactly match the pinned expected value.

  2. Prefer cryptographically signed release manifests and verify signatures against a pinned publisher public key.

  3. Ensure the signed manifest binds the version, filename, size, and digest.

  4. Download into a temporary file, verify it, and only then move it into the extraction workflow.

  5. Add explicit connect and read timeouts to both requests.get() calls to avoid indefinite hangs.

  6. Document the trust boundary and provide an intentional upgrade process for changing the pinned release or expected digest.

other

Error
Location
scripts/data_client.py:68
Finding

Core Query APIs Silently Return Fabricated Financial Data

Content
View full analysis

Vulnerability Details

File Location: scripts/data_client.py, lines 68-83, 115-121, and 137-138
Vulnerability Type: Financial data integrity failure and misleading implementation behavior
Risk Level: High

Vulnerable Code

python
dates = pd.date_range(start_date, end_date, freq='B')  # 工作日
n = len(dates)

data = {
    'ts_code': ts_code,
    'trade_date': dates,
    'open': np.random.uniform(10, 20, n),
    'high': np.random.uniform(15, 25, n),
    'low': np.random.uniform(8, 18, n),
    'close': np.random.uniform(12, 22, n),
    'vol': np.random.uniform(100, 1000, n),
    'amount': np.random.uniform(1000, 10000, n),
}

return pd.DataFrame(data)
python
# TODO: 实现涨跌停数据查询
return {
    'ts_code': ts_code,
    'trade_date': date,
    'up_limit': 20.0,
    'down_limit': 10.0,
    'limit_status': 'normal'
}
python
# TODO: 实现股票列表查询
return ['000001.SZ', '000002.SZ', '600000.SH']

Technical Analysis

The public API and documentation present these methods as financial-data query operations, but the methods do not read the downloaded dataset:

  • get_stock_daily() creates random prices, volume, and amount values.
  • get_limit_data() returns fixed placeholder values.
  • get_stock_list() returns a hard-coded list.

The resulting records are not explicitly labeled as samples or synthetic data. They are returned through the same interfaces documented for genuine historical market data and can also be exported to CSV, JSON, or Excel.

The random ranges do not enforce market invariants. For example, a generated low may exceed a generated open or close, and a generated high may be inconsistent with other values. The included tests only check that a nonempty table and expected columns exist, so they do not detect that no real data was queried.

Attack Path

  1. A user installs the Skill based on its stated investment-data capabilities.
  2. The user calls get_stock_daily(), get_limit_data(), or get_stock_list() through the d ...[truncated 1315 chars]
Remediation
View remediation

Remediation Suggestions

  1. Implement actual reads from the declared dataset for every documented query method.

  2. Until implementation is complete, fail explicitly:

python
raise NotImplementedError(
    "Real market-data retrieval is not implemented; no synthetic data was returned."
)
  1. If synthetic data is intentionally supported:

    • Require an explicit synthetic=True option.
    • Label returned frames and exports as synthetic.
    • Use a deterministic seed when reproducibility is required.
    • Generate internally consistent OHLC values.
    • Keep synthetic APIs separate from production data APIs.
  2. Validate requested stock codes and dates, including ensuring that the start date does not follow the end date.

  3. Add deterministic fixture-based tests that compare returned values with known records from a small trusted dataset.

  4. Add tests proving that production methods access the configured data files and never silently fall back to placeholders.

  5. Correct the README, Skill description, and examples so that implemented and unimplemented capabilities are clearly distinguished.

  6. Prevent exports unless the data source and provenance are known and attached to the output metadata.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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
Findings (26)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The documented behavior materially misrepresents what the skill actually provides: it claims real, validated financial data but reportedly returns mock, fixed, or empty data and may invoke downloader/update subprocesses instead. In a financial context, inaccurate or fabricated market data can mislead investment decisions while hidden operational behavior adds unexpected execution and data-handling risk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The method advertised as returning high-quality A-share market data instead generates random placeholder values, creating materially false financial output while presenting it as legitimate investment data. In a finance-oriented skill, this can mislead downstream analytics, trading decisions, or user trust in a way that is directly harmful even without traditional code execution.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill documentation is written entirely in Chinese from the opening description onward, with no indication that users may choose another language or that the skill is intentionally limited to a Chinese-only audience. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill declares shell, network, and environment-dependent behavior through installation steps, downloader/update commands, and cron tasks, but does not define any explicit tool scope or permissions boundary. This can cause the agent platform to invoke the skill with broader capabilities than users expect, increasing the chance of unintended network access, local file writes, or command execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Broad trigger phrases like general stock and financial data terms make accidental invocation more likely, especially in a shared assistant environment handling ordinary finance questions. Because this skill can download data, access the network, and write local files, unintended activation increases exposure to unnecessary side effects and user confusion.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill advertises automatic downloads and scheduled updates without clearly disclosing that it performs network access and writes data to local storage. This weakens informed consent and can lead to unexpected persistence, bandwidth use, or execution of update tasks in environments where such side effects are sensitive.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The skill is described as a data-query client, but it also performs dataset mutation by invoking an external updater script. This expands the skill's behavior beyond user expectations, introducing an execution side effect and a trust boundary on another local script that may fetch or modify data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The update method triggers an external script without confirmation, warning, or dry-run behavior, creating an undisclosed side effect in a skill that otherwise appears to be for data retrieval. That can lead to unintended downloads, file modifications, network access, or execution of compromised local code if the helper script is altered.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Launching a local script via subprocess gives the skill code-execution capability not obviously required for simple stock-data queries. In this context, that hidden capability is more dangerous because users may invoke a seemingly harmless data client without realizing it can run auxiliary code with the caller's privileges.

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 · scripts/data_client.py (reported line 169)May include surrounding context.

python
logger.info("更新数据...")
        # 调用下载脚本
        import subprocess
        result = subprocess.run(
            ['python', 'scripts/download_data.py', '--latest'],
            capture_output=True,
            text=True

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The file's user-facing natural-language strings, including the module docstring, CLI description, help text, progress messages, and errors, are entirely in Chinese. This imposes a specific language on all users without any opt-in, language selection, or documented locale-specific justification, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
77% confidence
Finding

The script fetches release metadata and archives from external GitHub endpoints and then extracts the downloaded tarball without any integrity verification such as a pinned checksum or signature validation. In this skill context, downloading third-party financial data is expected, but trusting remote content blindly increases supply-chain risk: if the upstream repo, release artifact, or network path is compromised, users could ingest malicious or tampered files.

Content

Scanner excerpt · scripts/download_data.py (reported line 23)May include surrounding context.

python
def get_latest_release() -> str:
    """获取最新 release 版本"""
    url = "https://api.github.com/repos/chenditc/investment_data/releases/latest"
    resp = requests.get(url)
    resp.raise_for_status()
    data = resp.json()

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The natural-language strings in the module docstring, argument parser description, and help text are all Chinese, with no option for users to choose another language and no justification that the tool is region-specific. That creates a locale policy concern because the skill effectively enforces a single language without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

The manifest description and the rest of the skill documentation are presented entirely in Chinese and focused on A-share data, but there is no statement that the language is user-selectable or intentionally restricted to a Chinese-speaking audience. Under the policy, forcing a specific language without opt-in can be a natural-language policy issue unless justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This markdown file presents all field documentation and notes exclusively in Chinese, and it does not provide an alternative language option or indicate that the skill is intentionally limited to Chinese-speaking users. Under the policy, forcing a specific language without user opt-in is a natural-language locale violation.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is specified with a lower bound only (pandas>=2.0.0), which makes builds non-reproducible and can unexpectedly pull in future releases with regressions or newly introduced security issues. In a data-processing skill, this increases supply-chain uncertainty even though the file itself does not prove exploitation.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
pandas>=2.0.0
numpy>=1.24.0
requests>=2.31.0
pyyaml>=6.0

Unverifiable Dependency: pandas has 1 known advisory(ies) (CVE-2020-13091 (** DISPUTED ** pandas through 1.0.3 can unserialize and execute commands from an)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
82% confidence
Finding

The manifest does not pin pandas, so it is impossible to determine from this file alone whether the installed version is affected by known advisories. This uncertainty weakens vulnerability management and reproducibility, though the cited pandas advisory is disputed and the package is primarily a data-processing library.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

numpy>=1.24.0 is unpinned, so installations may resolve to different versions over time, reducing reproducibility and making it harder to verify exposure to known vulnerabilities. This is a supply-chain hygiene issue rather than direct malicious behavior.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
pandas>=2.0.0
numpy>=1.24.0
requests>=2.31.0
pyyaml>=6.0
openpyxl>=3.1.0  # Excel 导出支持

Unverifiable Dependency: numpy has 16 known advisory(ies) (CVE-2014-1859 (Numpy arbitrary file write via symlink attack); CVE-2021-41495 (NumPy NULL Pointer Dereference); CVE-2021-33430 (NumPy Buffer Overflow (Disputed)) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
88% confidence
Finding

Because numpy is unpinned, the actual resolved version may or may not be affected by known advisories, making security posture unverifiable from the manifest. This is mainly a dependency-governance weakness rather than evidence of an active exploit path in the file.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

requests>=2.31.0 allows any later version, which can introduce unknown behavior changes or dependency-chain security issues. Because requests is commonly used for outbound network access, version drift can have greater security consequences than a purely local library.

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
pandas>=2.0.0
numpy>=1.24.0
requests>=2.31.0
pyyaml>=6.0
openpyxl>=3.1.0  # Excel 导出支持

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The manifest leaves the requests version effectively open-ended, so known advisories affecting some releases cannot be ruled out. Since requests often handles HTTP traffic, unresolved version exposure can materially affect confidentiality or integrity if vulnerable code paths are used elsewhere in the skill.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

pyyaml>=6.0 is not pinned, so the environment may install versions that differ across deployments and may be affected by parser-related security issues. YAML parsers are security-sensitive when they may process external or untrusted content, making version control important.

Content

Scanner excerpt · requirements.txt (reported line 4)May include surrounding context.

text
pandas>=2.0.0
numpy>=1.24.0
requests>=2.31.0
pyyaml>=6.0
openpyxl>=3.1.0  # Excel 导出支持

Unverifiable Dependency: pyyaml has 8 known advisory(ies) (CVE-2019-20477 (Deserialization of Untrusted Data in PyYAML); CVE-2020-1747 (Improper Input Validation in PyYAML); CVE-2020-14343 (Improper Input Validation in PyYAML) +5 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
94% confidence
Finding

PyYAML has a history of unsafe deserialization issues, and because the dependency is not pinned, this file cannot prove that a safe release will be installed. In a data-ingestion skill, that ambiguity is more concerning if YAML configuration or external data is parsed anywhere in the project.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: openpyxl has 2 known advisory(ies) (CVE-2017-5992 (Improper Restriction of XML External Entity Reference in Openpyxl); CVE-2017-5992 (Openpyxl 2.4.1 resolves external entities by default, which allows remote attack)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
86% confidence
Finding

openpyxl is unpinned, so the deployed version could fall within a range affected by historic XML-related issues, and the manifest does not allow verification. This is lower risk here because the requirement already sets a relatively recent minimum (>=3.1.0), which is likely newer than the cited 2017 advisory range, but exact safety still cannot be proven without pinning.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

This code performs a file-writing operation via client.export_data(...) when --output is supplied, but the script provides no confirmation prompt, no logging/print disclosure at write time, and no explanatory comment about the side effect. For a code file, file writes are safety-relevant operations that should have some visible user disclosure unless already clearly warned elsewhere.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.