Back to skill

Security audit

ifind-finance-data/同花顺金融数据

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate iFinD finance-data client, but it stores an auth token locally and disables TLS certificate checks when sending that token and queries over the network.

Review before installing. Use only if you are comfortable sending finance queries to iFinD and storing an iFinD token locally. Do not use the bundled clients on untrusted networks until TLS verification is enabled; keep mcp_config.json out of version control, restrict access to it, and rotate any token used with these scripts if exposure is possible.

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
call-node.js:39
Finding
TLS Certificate Validation Disabled in the Node.js MCP Client## Vulnerability Details **File Location**: `call-node.js`, lines 39–48 **Vulnerability Type**: Improper TLS certificate validation **Risk Level**: High ### Vulnerable Code ```javascript const options = { hostname: url.hostname, port: url.port, path: url.pathname, method: 'POST', headers: headers(t), timeout: timeout * 1000, rejectUnauthorized: false, }; ``` ### Technical Analysis The HTTPS request configuration explicitly sets `rejectUnauthorized` to `false`. This disables verification of the remote server's TLS certificate, including its trust chain and hostname identity. Although the connection remains encrypted, the client cannot establish that it is communicating with the legitimate iFinD MCP server. Any certificate presented by an intercepted or impersonated endpoint will be accepted. The client includes the configured authentication token in the `Authorization` header for initialization, notification, tool-listing, and tool-invocation requests. Consequently, a network-positioned attacker can obtain the token by presenting an untrusted certificate. The attacker can also inspect financial queries and return manipulated MCP responses. ### Attack Path 1. A user places a valid iFinD MCP authentication token in `mcp_config.json`. 2. The Node.js client constructs an HTTPS request containing the token in the `Authorization` header. 3. An attacker gains a network interception position, compromises a proxy, or redirects the target through DNS or routing manipulation. 4. The attacker presents a certificate that would normally fail trust or hostname validation. 5. The client accepts the certificate because `rejectUnauthorized` is disabled. 6. The attacker captures the authentication token and submitted financial-data queries. 7. The attacker may replay the token against the service within its granted permissions or return fabricated MCP data to the client. ### Impact Assessme ...[truncated 618 chars]
Remediation
## Remediation Suggestions 1. Remove `rejectUnauthorized: false` and retain the secure Node.js default: ```javascript const options = { hostname: url.hostname, port: url.port, path: url.pathname, method: 'POST', headers: headers(t), timeout: timeout * 1000, }; ``` 2. Do not introduce an environment-controlled option that silently disables certificate validation. 3. If the service relies on a private certificate authority, provide a narrowly scoped CA certificate through the `ca` option instead of disabling verification. 4. Validate failures using an invalid, expired, self-signed, and hostname-mismatched certificate to ensure that each connection is rejected. 5. Rotate any authentication token that may previously have been transmitted using this client over an untrusted network. 6. Apply least-privilege scopes and expiration to MCP authentication tokens where supported.

T09 · Insecure Skill Coding Practices

Error
Location
call.py:35
Finding
TLS Certificate Validation Disabled in the Python MCP Client## Vulnerability Details **File Location**: `call.py`, lines 35–42 and 73–80 **Vulnerability Type**: Improper TLS certificate validation **Risk Level**: High ### Vulnerable Code The primary request helper disables certificate validation: ```python def _post(t, payload, timeout=60): resp = requests.post( SERVERS[t], json=payload, headers=_headers(t), verify=False, timeout=timeout, ) ``` The initialized-session notification independently repeats the insecure setting: ```python notify = {"jsonrpc": "2.0", "method": "notifications/initialized"} requests.post( SERVERS[t], json=notify, headers=_headers(t), verify=False, timeout=10, ) ``` ### Technical Analysis Passing `verify=False` to `requests.post` disables TLS certificate-chain and hostname verification. The weakness affects all requests sent through `_post`, including MCP initialization, tool listing, and tool invocation. It also affects the separate initialized-session notification. The Python client sends the configured authentication token in the `Authorization` header. Disabling server authentication permits a network-positioned attacker to impersonate the hard-coded MCP endpoint with any certificate, intercept the bearer token and query contents, and modify server responses. This is not mitigated by the endpoint using an `https://` URL. TLS confidentiality is insufficient when the peer's identity is not authenticated. ### Attack Path 1. A user configures a valid authentication token in `mcp_config.json`. 2. The Python client calls the MCP service through `_post` or sends the initialized-session notification. 3. A malicious network gateway, proxy, DNS response, or routing position directs the connection to an attacker-controlled TLS endpoint. 4. The endpoint supplies an invalid, self-signed, or hostname-mismatched certificate. 5. The `requests` library accepts ...[truncated 910 chars]
Remediation
## Remediation Suggestions 1. Remove every `verify=False` argument and use the secure `requests` default: ```python resp = requests.post( SERVERS[t], json=payload, headers=_headers(t), timeout=timeout, ) ``` ```python requests.post( SERVERS[t], json=notify, headers=_headers(t), timeout=10, ) ``` 2. If a private certificate authority is required, set `verify` to the path of a controlled CA bundle rather than to `False`. 3. Centralize all HTTP requests in one hardened session so that security settings are not duplicated or inconsistently applied. 4. Add tests confirming rejection of self-signed, expired, untrusted, and hostname-mismatched certificates. 5. Rotate authentication tokens that may have been used with the vulnerable client on untrusted networks. 6. Configure short token lifetimes and least-privilege access where the MCP service supports them. 7. Treat TLS warnings as failures rather than suppressing them.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (19)

MCP Config Access

High
Category
Agent Snooping
Content
## 首次使用 / First-Time Setup

- **配置密钥 / Configure Token**:`mcp_config.json` 用于存储用户密钥,如不存在有效密钥,需提示用户到"iFinD终端-工具-常用工具-数据MCP"获取密钥,帮助其完成密钥写入,或手动写入
  - `mcp_config.json` stores the user auth token. If no valid token exists, guide user to obtain one from "iFinD Terminal - Tools - Common Tools - Data MCP"

## 数据范围 / Data Coverage
Confidence
95% confidence
Finding
The skill explicitly directs access to mcp_config.json containing the user's auth token and tells the agent to help write the token there. This creates direct credential-handling behavior inside the skill and increases the risk of secret exposure via file reads, writes, generated scripts, error output, or unintended reuse across sessions.

MCP Config Access

High
Category
Agent Snooping
Content
## 注意事项 / Notes

1. 配置文件 `mcp_config.json` 需要包含有效的 `auth_token`(两个方案共用)
   - `mcp_config.json` requires a valid `auth_token` (shared by both solutions)
2. 请求地址已经内置在请求脚本 `call.py` 和 `call-node.js` 内部,无需重新配置
   - Request URLs are built into scripts, no need to reconfigure
Confidence
95% confidence
Finding
This note reiterates that mcp_config.json must contain a valid shared auth_token for both implementations, confirming reliance on a plaintext local credential file. Shared-token file usage broadens the blast radius of any file disclosure or accidental inclusion in generated artifacts, and increases the risk of compromise if the workspace is synced or inspected by other tools.

MCP Config Access

High
Category
Agent Snooping
Content
## 注意事项 / Notes

1. 配置文件 `mcp_config.json` 需要包含有效的 `auth_token`(两个方案共用)
   - `mcp_config.json` requires a valid `auth_token` (shared by both solutions)
2. 请求地址已经内置在请求脚本 `call.py` 和 `call-node.js` 内部,无需重新配置
   - Request URLs are built into scripts, no need to reconfigure
3. 所有函数返回结果需检查 `ok` 字段确认请求是否成功
Confidence
90% confidence
Finding
Skill accesses MCP server configuration files (mcp.json). MCP configs contain server URLs, authentication tokens, and tool definitions — reading them allows the skill to discover and potentially abuse other tool integrations.

MCP Config Access

High
Category
Agent Snooping
Content
from pathlib import Path
import requests

CONFIG = json.loads(Path("mcp_config.json").read_text(encoding="utf-8"))
AUTH_TOKEN = CONFIG["auth_token"]

BASE = "https://api-mcp.51ifind.com:8643/ds-mcp-servers"
Confidence
90% confidence
Finding
Skill accesses MCP server configuration files (mcp.json). MCP configs contain server URLs, authentication tokens, and tool definitions — reading them allows the skill to discover and potentially abuse other tool integrations.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill documents use of local files and outbound network access, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates an authorization gap where an agent may invoke broader file or network capabilities than a user expects, especially because the skill also references local token storage and built-in request scripts.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger list includes broad generic phrases like financial data, market data, stock query, and news-related terms that could match many ordinary requests. Over-broad activation increases the chance the skill runs unintentionally, exposing local token-backed network actions in contexts where the user did not explicitly ask to use this external service.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The skill instructs users to place an auth token into mcp_config.json but does not clearly warn about secure handling, storage, rotation, or the risk of exposing that token through logs, prompts, or shared workspaces. Because the skill is designed to make authenticated external requests, insufficient token-handling guidance materially increases the chance of credential leakage.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The file loads `mcp_config.json` and extracts `auth_token`, which is a credential-sensitive operation under this rule. The code contains no explanatory comment, disclosure, or prompt informing the user that local credentials will be accessed and used.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
This code builds HTTP headers containing an Authorization token and later sends request payloads to remote MCP servers, which may include user-supplied parameters. Aside from an instruction not to run the script directly, there is no confirmation prompt, warning comment, or user-facing disclosure that credentials and request data will be transmitted over the network.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
This code reads an auth token from a local configuration file and transmits it in outbound requests, but there is no docstring, comment, log message, or confirmation indicating that credentials will be used and sent to a remote service. For a code file, credential access and transmission are safety-relevant operations that require some visible disclosure unless clearly documented elsewhere.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill posts JSON payloads, including tool names and arguments, to external HTTPS endpoints, but the code provides no user-facing notice, prompt, or explanatory comment that user-supplied parameters may be sent off-host. This matches the missing-warning criterion for network/HTTP calls that transmit user or system data.

External Transmission

Medium
Category
Data Exfiltration
Content
def _post(t, payload, timeout=60):
    resp = requests.post(
        SERVERS[t],
        json=payload,
        headers=_headers(t),
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
def _post(t, payload, timeout=60):
    resp = requests.post(
        SERVERS[t],
        json=payload,
        headers=_headers(t),
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Medium
Confidence
99% confidence
Finding
TLS certificate verification is explicitly disabled for outbound API requests with verify=False. This allows man-in-the-middle interception or tampering of financial queries, responses, session identifiers, and the Authorization token, which is especially dangerous for a finance-data integration that automatically communicates with remote servers.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
SERVERS[t],
        json=payload,
        headers=_headers(t),
        verify=False,
        timeout=timeout,
    )
    data = None
Confidence
99% confidence
Finding
Using verify=False creates an unsafe default that suppresses server certificate validation for all normal POST requests. This makes the client trust any presented certificate, exposing financial data traffic, auth headers, and JSON-RPC payloads to interception or modification.

Context-Inappropriate Capability

Medium
Confidence
98% confidence
Finding
The initialization notification also disables TLS verification, so the insecure transport applies not only to tool calls but also to session-establishment traffic. An attacker on the network could spoof or tamper with MCP session setup and potentially hijack or disrupt subsequent authenticated interactions.

Unsafe Defaults

Medium
Category
Tool Misuse
Content
SERVERS[t],
        json=notify,
        headers=_headers(t),
        verify=False,
        timeout=10,
    )
Confidence
99% confidence
Finding
Using verify=False in the initialization notification repeats the same unsafe default during session bootstrap. Because session establishment is foundational to later requests, compromise at this step can enable spoofed sessions, response manipulation, or denial of service.

Intent-Code Divergence

Low
Confidence
82% confidence
Finding
The message at L184 tells users not to directly execute the request script, implying a non-executing or guidance-only role for this entry point. However, the module immediately exports callable functions at L187 that initialize sessions and send live HTTPS/HTTP requests to remote iFinD MCP servers, so the documentation text understates and partially contradicts the module's actual purpose.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The only user-facing message is presented solely in Chinese and does not offer a language choice or indicate that the skill is region- or language-specific. This creates a natural-language policy issue because the skill imposes a locale/language constraint without opt-in or justification in the file.

Static analysis

No suspicious patterns detected.