Back to skill

Security audit

eastmoney skills

Security checks for vulnerabilities and agentic risk

Overview

The skill appears purpose-built for Eastmoney watchlist management, but it can immediately change account-linked financial watchlist data from natural-language input without confirmation.

Review before installing if you use this with a real Eastmoney account. Only run add/delete commands when you intend to change your watchlist, prefer setting MX_APIKEY through a trusted environment rather than a .env file, and treat generated CSV/raw JSON files as account-related data.

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
scripts/mx_self_select.py:154
Finding
Spreadsheet Formula Injection in Exported CSV Data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/mx_self_select.py:154-166` **Vulnerability Type**: CSV formula injection **Risk Level**: Medium ### Vulnerable Code ```python for stock in data_list: csv_row = {} for key, title in column_name_map.items(): csv_row[title] = stock.get(key, "") csv_rows.append(csv_row) with open(csv_path, "w", newline="", encoding="utf-8-sig") as f: writer = csv.DictWriter(f, fieldnames=fieldnames) writer.writeheader() for row in csv_rows: writer.writerow(row) ``` ### Technical Analysis Column titles and stock values received from the remote API are written directly to a CSV file without neutralizing spreadsheet formula prefixes. Python's `csv` module performs CSV syntax quoting, but it does not prevent spreadsheet applications from interpreting values beginning with `=`, `+`, `-`, or `@` as formulas. Exploitation requires an attacker to influence the API response, such as through an upstream service compromise or malicious data entering the service. When a user opens the generated file in a spreadsheet application, an injected value may be evaluated as a formula. The exact result depends on the spreadsheet product and its security configuration. ### Attack Path 1. An attacker gains control over, or otherwise influences, a column title or stock-data value returned by the configured API. 2. The attacker supplies a value beginning with a spreadsheet formula marker, such as `=`, `+`, `-`, or `@`. 3. The Skill copies that value into `mx_self_select_*.csv` without neutralization. 4. The user opens the generated CSV file in a spreadsheet application. 5. The application interprets the attacker-controlled cell as a formula. 6. Depending on the spreadsheet and enabled features, the formula may initiate an external request, expose spreadsheet data, mislead the user, or invoke other dangerous spreadsheet functionality. ### Impact Assessment The Skill itself does not directly exec ...[truncated 520 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Apply a dedicated CSV-cell neutralization function to every externally derived header and value before writing: ```python def neutralize_csv_formula(value): if value is None: return "" text = str(value) if text.startswith(("=", "+", "-", "@")): return "'" + text return text ``` Use the function for both column titles and row values. Consider handling leading whitespace, tabs, carriage returns, and other control characters that some spreadsheet products may ignore before detecting a formula. Additional hardening measures include: - Define a fixed allowlist of expected API columns instead of accepting arbitrary remote column titles. - Validate response types and reject unexpected structures. - Document that CSV files contain remote data and should be opened using protected-view settings. - Add tests covering values such as `=1+1`, `+SUM(1,1)`, `-1+2`, `@SUM(1,1)`, and formula prefixes preceded by whitespace or control characters. ]]>

T08 · Insecure Dependencies

Note
Location
scripts/requirements.txt:1
Finding
Unbounded and Unlocked Third-Party Dependency<![CDATA[ ## Vulnerability Details **File Location**: `scripts/requirements.txt:1` **Vulnerability Type**: Non-reproducible dependency resolution **Risk Level**: Low ### Vulnerable Code ```text requests>=2.31.0 ``` ### Technical Analysis The dependency declaration permits any future version of `requests` at or above version 2.31.0 and does not specify package hashes. Consequently, installations performed at different times may resolve to different, unaudited package versions and transitive dependency sets. No malicious package or currently vulnerable resolved version was identified in the reviewed project. The risk arises from the lack of reproducibility and integrity locking: a future compromised, defective, or incompatible release satisfying this constraint could be selected automatically. ### Attack Path 1. A future version of `requests`, or one of its transitive dependencies, is compromised or contains an exploitable defect. 2. That version remains compatible with the broad `>=2.31.0` constraint. 3. A user installs the project dependencies without a lock file or hash verification. 4. The package installer resolves and downloads the affected version. 5. Malicious installation behavior, import-time code, or vulnerable runtime functionality executes in the context of the user installing or running the Skill. This path depends on a future upstream or package-distribution compromise; the audited repository does not itself contain evidence of such a compromise. ### Impact Assessment Potential impact is bounded by the privileges of the account that installs or runs the dependency. In a compromised supply-chain scenario, this could include access to the Skill process's files, environment variables such as `MX_APIKEY`, outbound network access, and modification of files writable by that account. The broad constraint alone does not provide elevated privileges or establish that exploitation is currently possible. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Pin `requests` and all transitive dependencies to versions that have been reviewed and tested. - Generate a lock file or fully resolved requirements file for reproducible installations. - Require package hashes, for example by using `pip-compile --generate-hashes` and installing with `pip --require-hashes`. - Use an approved package index and prevent fallback to untrusted indexes. - Automate dependency vulnerability scanning and controlled update reviews. - Periodically regenerate the lock file so security updates are adopted deliberately rather than through unrestricted resolution. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (12)

Tainted flow: 'headers' from os.environ.get (line 71, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
}
    
    try:
        response = requests.post(QUERY_URL, headers=headers, json={}, timeout=30)
        response.raise_for_status()
        return response.json()
    except Exception as e:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'headers' from os.environ.get (line 71, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
}
    
    try:
        response = requests.post(MANAGE_URL, headers=headers, json=data, timeout=30)
        response.raise_for_status()
        return response.json()
    except Exception as e:
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Credential Access

High
Category
Privilege Escalation
Content
apikey = os.environ.get("MX_APIKEY", "")
    if not apikey:
        # 尝试从.env文件读取
        env_file = os.path.join(os.path.dirname(os.path.dirname(__file__)), ".env")
        if os.path.exists(env_file):
            try:
                with open(env_file, "r") as f:
Confidence
83% confidence
Finding
Falling back to reading a plaintext .env file for an API key increases the risk of credential exposure through accidental commits, weak filesystem permissions, shared workspaces, or container/image leakage. While common in development, it is a credential-handling weakness in a skill that accesses a user account and performs remote actions on that account.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill advertises capabilities that involve environment-variable access, file output, and external network requests, but it does not declare any explicit tool scope or permissions boundary. This weakens reviewability and least-privilege enforcement, increasing the chance that an agent runtime grants broader access than users expect when handling account-linked watchlist data and API credentials.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The manifest description and usage instructions are entirely in Chinese and explicitly describe operation through natural-language queries, but they do not state that the skill is Chinese-only or offer any language choice. This can violate a language/locale policy when users are not given opt-in or an alternative locale.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The skill transmits user commands and an API credential to a remote service but does not provide an explicit user-facing notice at execution time that data will leave the local environment. In a tool/agent context, this can create privacy and consent issues because natural-language inputs may contain more information than the user realizes will be sent upstream.

External Transmission

Medium
Category
Data Exfiltration
Content
}
    
    try:
        response = requests.post(QUERY_URL, headers=headers, json={}, timeout=30)
        response.raise_for_status()
        return response.json()
    except Exception as e:
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
}
    
    try:
        response = requests.post(MANAGE_URL, headers=headers, json=data, timeout=30)
        response.raise_for_status()
        return response.json()
    except Exception as e:
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill performs state-changing add/delete watchlist operations immediately based on CLI input or natural-language text, without confirmation, dry-run, or explicit acknowledgement. In an agent setting, ambiguous prompts, prompt injection in upstream context, or user misunderstanding could cause unintended portfolio/watchlist modifications.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
SKILL.md 在配置与前置要求中多次声明应使用环境变量 `MX_APIKEY`,但安全注意事项又写成 `EASTMONEY_APIKEY`。这会让技能声明的使用方式与文档中的安全说明发生直接冲突,属于文档意图层面的矛盾。

Unpinned Dependencies

Low
Category
Supply Chain
Content
requests>=2.31.0
Confidence
93% confidence
Finding
The dependency is specified as `requests>=2.31.0` without an upper bound or exact pin, which makes builds non-reproducible and can silently introduce vulnerable or incompatible versions over time. In a skill that interacts with account-backed data and external services, dependency drift increases supply-chain risk and makes security posture unverifiable.

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
90% confidence
Finding
Because `requests` is not pinned, it is impossible to verify whether the installed version includes fixes for known advisories affecting that package. This uncertainty is especially relevant here because the skill appears to access account and market data, so any vulnerable HTTP client behavior could affect credential handling, request integrity, or data exposure depending on the runtime version resolved.

Static analysis

No suspicious patterns detected.