Back to skill

Security audit

China iFinD Skill(同花顺Skill)

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate iFinD financial API helper, but it asks users to share and store a long-lived token unsafely and exposes portfolio-changing actions.

Review before installing. Use only with a secure secret-management path for IFIND_REFRESH_TOKEN, avoid pasting tokens into chat, restrict file permissions if local storage is unavoidable, and do not allow portfolio_manage mutation actions unless you explicitly intend to let the agent alter portfolio data.

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
references/API_REFERENCE.md:13
Finding
Command Injection Through Unsafe Refresh Token Configuration<![CDATA[ ## Vulnerability Details **File Location**: `references/API_REFERENCE.md:13-16` **Vulnerability Type**: Shell command injection through unsafe interpolation of user-controlled credential data **Risk Level**: High ### Vulnerable Code ```bash 用户提供 token 后,写入配置: ```bash sed -i '' 's/^IFIND_REFRESH_TOKEN=.*/IFIND_REFRESH_TOKEN=用户提供的token/' ~/.openclaw/skills/ifind-api/.env ``` ``` The instructions direct the Agent to replace the placeholder with a refresh token supplied by the user and then execute the resulting shell command. ### Technical Analysis The user-provided refresh token is inserted into a single-quoted shell command without shell escaping or safe argument handling. If an Agent follows these instructions through direct string substitution, a malicious token containing a single quote can terminate the quoted `sed` expression. Subsequent characters may then be interpreted as shell syntax. Even when shell command execution is not achieved, `sed` replacement metacharacters such as `&`, backslashes, or the selected delimiter can alter or corrupt the resulting configuration value. Credential configuration is necessary for the Skill, but interpolating a credential into a shell command is not the minimum privilege or safest mechanism needed to perform that operation. ### Attack Path 1. The Skill determines that `IFIND_REFRESH_TOKEN` is missing. 2. It asks the user to provide a refresh token. 3. An attacker supplies a crafted value containing a quote followed by shell syntax. 4. The Agent substitutes that value for the documented placeholder. 5. The shell terminates the intended quoted `sed` expression and interprets the injected syntax. 6. The injected command executes with the same operating-system privileges as the Agent process. This path depends on the Agent following the documentation by performing direct textual interpolation, which is precisely the workflow prescribed by the reference. ### Impact Assessment Successful exploitation p ...[truncated 561 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Remove the `sed` command and do not embed secret values in dynamically constructed shell commands. - Accept the token through protected standard input or a secret-management interface rather than as part of a command line. - Use a dedicated Python configuration routine that: 1. Reads the token as opaque data. 2. Updates only the exact `IFIND_REFRESH_TOKEN` key. 3. Creates the destination file if it does not exist. 4. Writes through a temporary owner-only file. 5. Atomically replaces the destination. - If shell usage is unavoidable, pass the token through an environment variable and process it with a tool that does not interpret it as executable syntax. Do not rely solely on ad hoc quote escaping. - Validate that the token matches the documented iFinD token format, while still treating validation as defense in depth rather than as a substitute for safe argument handling. - Avoid exposing the token in process arguments, logs, terminal history, or Agent responses. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ifind-api.py:118
Finding
Access Token Cached in Plaintext Without Enforced File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ifind-api.py:118-167` **Vulnerability Type**: Insecure local storage of authentication credentials **Risk Level**: Medium ### Vulnerable Code ```python def get_access_token(refresh_token): cache_file = os.path.join(DATA_DIR, "access_token") # 检查缓存 try: stat = os.stat(cache_file) age = time.time() - stat.st_mtime if age < TOKEN_CACHE_TTL: with open(cache_file, "r", encoding="utf-8") as f: token = f.read().strip() if token: return token except OSError: pass start = time.time() try: data = http_post( IFIND_BASE_URL + "/get_access_token", headers={"refresh_token": refresh_token}, body=b"{}", ) except RuntimeError as e: latency_ms = int((time.time() - start) * 1000) log_entry("get_access_token", "error", str(e), "get_token", latency_ms) exit_error(f"获取 access_token 失败: {e}") try: result = json.loads(data) except json.JSONDecodeError: latency_ms = int((time.time() - start) * 1000) log_entry("get_access_token", "error", "invalid json", "get_token", latency_ms) exit_error(f"获取 access_token 响应异常: {data.decode('utf-8', errors='replace')}") data_obj = result.get("data") if not isinstance(data_obj, dict): latency_ms = int((time.time() - start) * 1000) log_entry("get_access_token", "error", "no data field", "get_token", latency_ms) exit_error("获取 access_token 失败,请检查 IFIND_REFRESH_TOKEN 是否有效") token = data_obj.get("access_token", "") if not token: latency_ms = int((time.time() - start) * 1000) log_entry("get_access_token", "error", "no access_token", "get_token", latency_ms) exit_error("获取 access_token 失败,请检查 IFIND_REFRESH_TOKEN 是否有效") try: with open(cache_file, "w", encoding="utf-8") as f: ...[truncated 2469 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Create `.data` with owner-only permissions (`0700`) and verify or repair its mode when it already exists. - Create the access-token cache with mode `0600`, for example by using `os.open` with explicit flags and permissions rather than relying on the process umask. - Write credentials to a newly created owner-only temporary file and atomically replace the cache file. - Where supported, reject symbolic links and verify that the destination is a regular file owned by the current user. - Check existing cache-file permissions before reading it; refuse to use a cache that is group-readable or world-readable. - Apply the same owner-only controls to the `.env` file containing `IFIND_REFRESH_TOKEN`. - Prefer an operating-system credential store or the platform’s secret-management facility instead of persistent plaintext files. - Preserve the existing behavior of excluding token values from logs and ensure future exception handling never includes request headers or credentials. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (16)

Natural-Language Policy Violations

High
Confidence
99% confidence
Finding
The skill explicitly tells the user to send their refresh token to the assistant, which is a direct request for a sensitive credential in natural language. Even if intended for convenience, this trains users to disclose secrets in chat and can expose long-lived API access to the model, logs, or other unintended handling paths.

Ssd 3

High
Confidence
99% confidence
Finding
Instructing users to send a refresh token directly to the assistant creates a social-engineering pattern that solicits credential disclosure. In this skill's context, the token is the primary authenticator for accessing financial data APIs, so exposure could allow unauthorized API usage, quota abuse, or access to account-linked data.

Credential Access

High
Category
Privilege Escalation
Content
**每次调用 API 前,先检查 `IFIND_REFRESH_TOKEN` 是否已配置:**

```bash
grep -q 'IFIND_REFRESH_TOKEN=.' ~/.openclaw/skills/ifind-api/.env 2>/dev/null && echo "ok" || echo "missing"
```

如果返回 `missing`,停止执行,提示用户提供 refresh_token。
Confidence
96% confidence
Finding
The instruction to probe for IFIND_REFRESH_TOKEN in a local .env file is credential-handling behavior. Even though it is framed as a presence check, it normalizes direct agent interaction with secret storage paths and can expose sensitive environment layout or lead to broader secret access patterns beyond the skill's stated purpose.

Credential Access

High
Category
Privilege Escalation
Content
用户提供 token 后,写入配置:

```bash
sed -i '' 's/^IFIND_REFRESH_TOKEN=.*/IFIND_REFRESH_TOKEN=用户提供的token/' ~/.openclaw/skills/ifind-api/.env
```

写入成功后告诉用户「已配置好,正在为你查询...」,然后继续执行 API 调用。
Confidence
98% confidence
Finding
The instruction to write a user-supplied refresh token into ~/.openclaw/skills/ifind-api/.env is direct credential persistence to disk by shell command. This is dangerous because it creates a durable secret on the filesystem without access-control guidance, audit boundaries, or confirmation that the storage location is secure, increasing risk of credential theft and unauthorized API access.

Context-Inappropriate Capability

High
Confidence
96% confidence
Finding
The skill is described as a financial data query tool, but the reference includes portfolio creation, cash movements, imports, and trade execution-like operations. In an autonomous or semi-autonomous agent, this materially broadens the capability from read-only analysis to state-changing financial actions, creating risk of unauthorized portfolio modification or user harm if the agent invokes the wrong endpoint.

Credential Access

High
Category
Privilege Escalation
Content
# ═══════════════════════════════════════════════════
# .env 加载
# ═══════════════════════════════════════════════════

def load_env():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# ═══════════════════════════════════════════════════
# .env 加载
# ═══════════════════════════════════════════════════

def load_env():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
# ═══════════════════════════════════════════════════

def load_env():
    env_file = os.path.join(SKILL_DIR, ".env")
    env = {}
    try:
        with open(env_file, "r", encoding="utf-8") as f:
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill declares access to an environment secret and describes file and network behavior, but does not declare an explicit tool scope such as permissions or allowed-tools. That mismatch weakens least-privilege controls and makes it harder for a host or reviewer to understand and constrain what the skill can access.

Natural-Language Policy Violations

Medium
Confidence
77% confidence
Finding
Most of the operational instructions and user-facing prompt text are only in Chinese, including the required setup and stop-condition guidance. Because no language choice or opt-in is offered, this can violate language/locale policy expectations for user-selectable interaction.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The documentation instructs the agent to inspect and modify a local ~/.openclaw/skills/ifind-api/.env file before serving a request. That is a state-changing local filesystem action involving credentials, and it is not necessary for a simple read-only financial data query workflow to tell the model to perform arbitrary shell-based secret management. In an agent setting, this expands the skill from data retrieval into local credential handling and file mutation, increasing risk of unintended secret exposure or tampering.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The document tells the user to provide a refresh token and instructs writing it directly into a local .env file, but gives no warning about secret sensitivity, storage implications, or safe handling. This encourages insecure credential collection and persistence, which can lead to token leakage, reuse by other local processes, or accidental disclosure in logs or support artifacts.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The portfolio management examples include creating portfolios, importing records, cash deposit/withdrawal, and trade operations without an explicit warning that these actions modify persistent financial state. In agent environments, lack of friction or warning around such operations increases the chance of accidental execution and user misunderstanding about consequences.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
The script reads the sensitive IFIND_REFRESH_TOKEN from the environment and uses it to request an access token via HTTP headers. While the code performs the action as part of its function, there is no visible confirmation prompt or user-facing disclosure in the executable path that sensitive credentials will be used and sent to a remote API.

Natural-Language Policy Violations

Low
Confidence
85% confidence
Finding
Natural-language policy violations include forcing a specific language without user opt-in. This reference file presents all instructions and examples in Chinese and does not indicate that the language is optional, selectable, or justified as region-specific documentation.

Natural-Language Policy Violations

Low
Confidence
77% confidence
Finding
The top-level docstring states 'Python 实现', and the script's user-facing messages are written only in Chinese, indicating a fixed language choice. Under the policy, forcing a specific language without user opt-in can be a natural-language policy violation unless the locale restriction is explicitly justified.

Static analysis

No suspicious patterns detected.