Back to skill

Security audit

Mx Finance Data

Security checks for vulnerabilities and agentic risk

Overview

This finance-data skill is mostly purpose-aligned, but it exposes the configured API key to any programmatic caller that overrides the API endpoint and writes untrusted API data into Excel files without formula neutralization.

Install only if you trust the Eastmoney API key and will run it in a constrained environment. Avoid passing or exposing api_base to users or configuration, restrict traffic to the documented Eastmoney endpoint, and treat generated XLSX files as untrusted external data when opening them in spreadsheet software.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/get_data.py:466
Finding

API Key Disclosure Through an Unrestricted API Endpoint

Content
View full analysis

Vulnerability Details

File Location: scripts/get_data.py, lines 466-489
Vulnerability Type: Credential disclosure through attacker-controlled network destination
Risk Level: High

Vulnerable Code

python
async def query_mx_finance_data(
        query: str,
        output_dir: Optional[Path] = None,
        api_base: Optional[str] = None,
) -> Dict[str, Any]:
    """
    执行金融数据主查询流程并输出文件结果。
    完成接口请求、业务状态校验、表格解析与文件写入。
    返回包含文件路径、行数及错误信息的结果字典。
    """
    output_dir = output_dir or _get_default_output_dir()
    output_dir = Path(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    url = api_base or DEFAULT_SEARCH_API_URL
    result = _make_result_base(query)

    try:
        body = _build_request_body(query)
        api_key = EM_API_KEY
        async with httpx.AsyncClient(timeout=30.0) as client:
            resp = await client.post(
                url,
                json=body,
                headers={
                    "Content-Type": "application/json",
                    "em_api_key": api_key,
                },
            )

Technical Analysis

The public query_mx_finance_data function accepts an unrestricted api_base parameter and uses it directly as the destination of an authenticated HTTP request. The EM_API_KEY credential is attached to the request regardless of the destination's scheme, hostname, port, or ownership.

Although the command-line interface does not expose api_base, other Python code can import and invoke this function. An integration that derives api_base from configuration or user-controlled input can therefore disclose the API key to an arbitrary server. The code does not require HTTPS or allowlist the documented East Money host.

Attack Path

  1. An attacker gains control over an application's api_base input or related configuration.
  2. The attacker supplies a URL under their control, such ...[truncated 873 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the api_base parameter from production-facing interfaces if endpoint substitution is unnecessary.
  2. If endpoint configurability is required for testing, separate the test client from the production authenticated client.
  3. Require an https scheme and allowlist the exact expected hostname, such as ai-saas.eastmoney.com.
  4. Reject URLs containing unexpected ports, embedded credentials, fragments, or noncanonical hostnames.
  5. Ensure credentials are never forwarded to a different origin during redirects. Keep redirects disabled or validate every redirect target before resending authenticated requests.
  6. Add tests confirming that HTTP URLs, attacker-controlled hosts, subdomain lookalikes, and malformed URLs are rejected before any request is sent.
  7. Rotate EM_API_KEY if the affected function has previously been invoked with an untrusted endpoint.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/get_data.py:426
Finding

Spreadsheet Formula Injection in Generated Excel Files

Content
View full analysis

Vulnerability Details

File Location: scripts/get_data.py, lines 426-430
Vulnerability Type: Spreadsheet formula injection
Risk Level: Medium

Vulnerable Code

python
with pd.ExcelWriter(file_path, engine="openpyxl") as writer:
    for table in tables:
        df = pd.DataFrame(table["rows"], columns=table["fieldnames"])
        df.to_excel(writer, sheet_name=table["sheet_name"], index=False)

Technical Analysis

Values parsed from the remote API response are placed into a pandas DataFrame and exported directly through openpyxl. No sanitization forces untrusted strings to remain literal text.

Spreadsheet applications may interpret strings beginning with formula markers such as =, +, -, or @ as formulas. Consequently, a malicious or compromised API response can embed active spreadsheet expressions in the generated workbook. Depending on the spreadsheet application's configuration and security controls, such formulas may create external links, initiate network requests, misrepresent financial values, or expose workbook data.

Attack Path

  1. An attacker compromises the upstream API, controls an API-compatible endpoint through the unrestricted api_base parameter, or otherwise causes a crafted value to appear in the API response.
  2. The response includes a cell value beginning with a spreadsheet formula marker.
  3. _table_to_rows preserves the value as a string and places it in table["rows"].
  4. _write_output_files exports the value without formula neutralization.
  5. A user opens the generated XLSX file in spreadsheet software.
  6. The spreadsheet application evaluates or prompts the user to enable the injected formula, potentially triggering attacker-selected spreadsheet behavior.

Exploitation depends on attacker influence over returned data and on the behavior and security configuration of the spreadsheet application used to open the file.

Impact Assessment

T ...[truncated 435 chars]

Remediation
View remediation

Remediation Suggestions

  1. Treat every API-derived cell value, header, entity name, and condition as untrusted.
  2. Before constructing the DataFrame, detect strings whose first non-whitespace character is =, +, -, or @.
  3. Neutralize such values by prefixing an apostrophe or by explicitly writing them as text cells.
  4. Preserve legitimate negative numeric values as numeric types rather than applying string-based sanitization indiscriminately.
  5. Consider writing cells through openpyxl with an explicit text data type when values originate from untrusted textual fields.
  6. Add regression tests covering all formula prefixes, leading whitespace, tabs, carriage returns, Unicode control characters, and nested API values.
  7. Document that generated files contain external data and should be opened with external links and automatic formula updates disabled.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • 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
Findings (3)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill requires an API key, performs network access, and writes output files, but it does not declare an explicit tool/permission scope. That creates a least-privilege and transparency problem: a host agent or user cannot easily constrain what the skill is allowed to access, increasing the risk of unintended secret use, network exfiltration, or unsafe file creation if the implementation is modified or behaves unexpectedly.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The module docstring and user-facing descriptions state the skill in Chinese only, including that it accepts natural-language questions, with no indication that other languages are supported or that the user can choose a locale. This is a natural-language policy issue because the skill imposes a specific language experience by default rather than offering opt-in or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The description includes both Chinese and English narrative text, but the rest of the skill instructions and examples are primarily in Chinese and do not state that users may choose their preferred language. This can amount to an implicit language policy constraint without explicit opt-in or documented language selection behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.