Back to skill

Security audit

Fund Trading Clawhub

Security checks for vulnerabilities and agentic risk

Overview

This looks like a simulated fund-trading skill, but it needs Review because it mishandles credentials and has important security and documentation inconsistencies.

Review before installing. Treat this as simulated trading only, verify the exact package/version you install, avoid using valuable production credentials, run it in an isolated environment, and rotate any client secret that appears in logs or plaintext config. Be especially cautious because the code contradicts its HTTPS configuration documentation and stores authentication material insecurely.

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/fund-trading.py:32
Finding
OAuth Credentials and Bearer Tokens Transmitted over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fund-trading.py:32`, `scripts/fund-trading.py:112-128`, `scripts/fund-trading.py:170-182`, and `scripts/fund-trading.py:220-226` **Vulnerability Type**: Plaintext transmission of authentication credentials **Risk Level**: High ### Vulnerable Code ```python API_ENDPOINT = "http://127.0.0.1:8080/openApi" ``` ```python url = f"{API_ENDPOINT}/openapi/v1/oauth/token" body = json.dumps( { "grantType": "client_credentials", "clientId": client_id, "clientSecret": client_secret, } ).encode("utf-8") req = urllib.request.Request( url, data=body, headers={"Content-Type": "application/json"}, method="POST" ) try: with urllib.request.urlopen(req, timeout=30) as response: result = json.loads(response.read().decode("utf-8")) ``` ```python url = f"{API_ENDPOINT}{path}" headers = { "Content-Type": "application/json", "Authorization": f"Bearer {token}", } data = json.dumps(body or {}).encode("utf-8") if method == "POST" else None req = urllib.request.Request(url, data=data, headers=headers, method=method) try: with urllib.request.urlopen(req, timeout=30) as response: return json.loads(response.read().decode("utf-8")) ``` ```python url = f"{API_ENDPOINT}/openapi/v1/channel/register" body = json.dumps({"username": username}).encode("utf-8") req = urllib.request.Request( url, data=body, headers={"Content-Type": "application/json"}, method="POST" ) ``` ### Technical Analysis The API endpoint is hardcoded with the plaintext `http://` scheme. The OAuth token request sends the account's client ID and client secret to this endpoint, while subsequent requests send a reusable bearer token in the `Authorization` header. Trading requests may also contain fund codes, order identifiers, monetary amounts, or redemption shares. Loopback traffic does not cross the external network under normal conditions, but HTTP provides no server authentication or t ...[truncated 1804 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the hardcoded HTTP endpoint with the documented environment-based configuration: ```python API_ENDPOINT = os.environ.get( "OPENAPI_URL", "https://openapi.nicaifu.com/openApi", ).rstrip("/") ``` 2. Reject plaintext endpoints by default: ```python from urllib.parse import urlparse parsed = urlparse(API_ENDPOINT) if parsed.scheme != "https": raise ValueError("OPENAPI_URL must use HTTPS") ``` 3. If plaintext loopback HTTP is required for development, require an explicit opt-in setting, emit a prominent warning, and never enable it by default. 4. Authenticate any local service rather than relying solely on the loopback address. 5. Ensure TLS certificates are validated using the default trusted certificate store; do not add certificate-verification bypasses. 6. Document the exact destination, transmitted fields, and credential handling behavior. 7. Add tests verifying that non-HTTPS production endpoints are rejected and that `OPENAPI_URL` is actually honored. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fund-trading.py:83
Finding
OAuth Client Secrets and Access Tokens Stored in Plaintext and Printed to Standard Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fund-trading.py:83-86`, `scripts/fund-trading.py:150-158`, and `scripts/fund-trading.py:247-266` **Vulnerability Type**: Insecure storage and disclosure of authentication secrets **Risk Level**: Medium ### Vulnerable Code ```python def save_config(config: dict): DATA_DIR.mkdir(parents=True, exist_ok=True) with open(CONFIG_FILE, "w", encoding="utf-8") as f: json.dump(config, f, ensure_ascii=False, indent=2) ``` ```python if access_token: if "tokens" not in config: config["tokens"] = {} config["tokens"][token_key] = { "access_token": access_token, "expires_at": time.time() + expires_in, } save_config(config) return access_token ``` ```python account = { "member_id": member_id, "username": username, "client_id": client_id, "client_secret": client_secret, "created_at": created_at, } config = load_config() config["accounts"].append(account) config["current_member_id"] = member_id save_config(config) print(f"✅ 注册成功!") print(f" 账户名: {username}") print(f" MEMBER_ID: {member_id}") print(f" CLIENT_ID: {client_id}") print(f" CLIENT_SECRET: {client_secret}") print(f" 创建时间: {created_at}") ``` ### Technical Analysis The configuration writer serializes account client secrets and bearer tokens directly into a plaintext JSON file. It does not explicitly create the file with owner-only permissions, verify ownership, or reject an unsafe existing symbolic link. Actual file accessibility therefore depends on the process umask and any pre-existing file permissions. The registration function also prints the complete client secret to standard output. Standard output may be retained in terminal scrollback, shell-session recordings, CI logs, Agent transcripts, monitoring systems, or redirected files. This behavior conflicts with the changelog statement that tokens are stored locally in encrypted form. No encryption or operatin ...[truncated 1412 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store client secrets and access tokens in the operating system's credential store rather than in the JSON configuration file. 2. If file-based storage is unavoidable, create the file atomically with mode `0600`, validate that it is owned by the current user, and reject symbolic links or unexpected file types. 3. Separate non-sensitive account metadata from authentication secrets. 4. Never print complete client secrets or access tokens. Display only a short redacted fingerprint if confirmation is necessary: ```python def redact(value: str) -> str: if not value: return "-" return value[:4] + "..." + value[-4:] ``` 5. Rotate credentials that may already have appeared in logs or existing plaintext configuration files. 6. Provide a secure migration procedure that removes old plaintext values after importing them into a credential store. 7. Correct the documentation and changelog unless encrypted or credential-store-backed persistence is actually implemented. 8. Add tests that verify secret values never appear in command output and that fallback files have owner-only permissions. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:42
Finding
Unpinned External Package Installation Bypasses Review of the Bundled Implementation<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:42-50`, `README.md:41-58`, and `clawhub.json:47-50` **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Code From `SKILL.md`: ```bash pip install fund-trading-skill ``` ```bash npm install -g fund-trading-skill ``` From `README.md`: ```bash # Global installation pip install fund-trading-skill # Installation using a mirror pip install fund-trading-skill -i https://pypi.tuna.tsinghua.edu.cn/simple ``` ```bash # Global installation npm install -g fund-trading-skill # Installation using a mirror npm install -g fund-trading-skill --registry=https://registry.npmmirror.com ``` From `clawhub.json`: ```json "install": { "pip": "pip install fund-trading-skill", "npm": "npm install -g fund-trading-skill" } ``` ### Technical Analysis The installation instructions retrieve packages by name without pinning an exact version or verifying an integrity hash. This causes users to install whatever release the selected registry currently serves rather than the source code contained in the audited project. The npm command additionally performs a global installation, increasing the package's reach and potentially exposing installation scripts or executables through a system-wide command path. The mirror-based commands add further registry infrastructure whose served artifact is not verified against a project-published digest. The Python and TypeScript packages downloaded through these instructions are not included in the reviewed directory. Their installation hooks, dependencies, and runtime behavior therefore cannot be confirmed as equivalent to `scripts/fund-trading.py`. ### Attack Path 1. A registry account, upstream package, dependency, or configured mirror is compromised, or a future package release introduces malicious behavior. 2. A user follows the documented unpinned pip or npm installation command. 3. The package manager resolves the la ...[truncated 929 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin exact package versions in all installation examples: ```bash python3 -m pip install fund-trading-skill==1.0.2 npm install fund-trading-skill@1.0.2 ``` 2. Publish and verify cryptographic hashes for released artifacts. For Python, distribute a hash-pinned requirements file and use `--require-hashes`. 3. Publish lockfiles or equivalent integrity metadata for transitive dependencies. 4. Avoid global npm installation where possible. Prefer a project-local dependency or an ephemeral, version-pinned invocation. 5. Make the bundled, reviewed script the default execution path when feasible. 6. Verify that PyPI, npm, and mirror artifacts are generated reproducibly from the tagged source and match published checksums. 7. Document that externally downloaded package versions are separate artifacts requiring their own security review. ]]>
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
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (13)

Intent-Code Divergence

High
Confidence
97% confidence
Finding
The manifest metadata presents the skill as a fund trading tool, while the description explicitly states it uses real fund prices but only virtual funds for simulated trading. In a finance context, this mismatch is dangerous because users or downstream agents may assume the skill can execute real trades or manage actual assets, leading to misuse, bad decisions, or unsafe integration into financial workflows.

Credential Access

High
Category
Privilege Escalation
Content
def get_token(
    client_id: str, client_secret: str, force_refresh: bool = False
) -> Optional[str]:
    """获取 OAuth 2.0 Access Token"""
    config = load_config()
    token_key = f"{client_id}"
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The code persists client_id/client_secret and OAuth tokens in a local JSON file and also prints the client secret to the console during registration. This exposes highly sensitive credentials to local users, shell history/log capture, terminal recording, backups, or malware on the host, enabling unauthorized trading API access and account takeover.

Missing User Warnings

High
Confidence
97% confidence
Finding
The skill performs real-money subscribe, redeem, and cancel operations immediately from command-line arguments with no secondary confirmation, dry-run, or risk acknowledgment. In a trading tool, this creates a substantial chance of accidental or scripted misuse leading to irreversible financial loss or unauthorized transactions if the environment or invocation is compromised.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The changelog states that the tool uses real fund NAV/market data but only virtual simulated funds, while the skill metadata describes it as a live fund trading tool. In a financial context, this inconsistency can materially mislead users or downstream agents about whether transactions are real, causing unsafe reliance, improper approvals, or accidental exposure of users to production trading flows.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The manifest and README repeatedly describe the skill as a real fund trading tool, but the important notice explicitly says '真实基金净值,虚拟资金交易' and that it is only for learning, strategy testing, and simulated trading. This is a semantic mismatch about the core behavior and user impact of the skill, not a minor implementation detail.

Missing User Warnings

Medium
Confidence
84% confidence
Finding
Although the README states that funds are virtual, it also documents actionable trading operations such as subscription, redemption, and cancellation. The command list does not include a nearby warning that these operations place or alter simulated orders and may change account state, which is relevant user-impacting behavior.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README documents local storage of client_id, client_secret, and access tokens in a plaintext config file under the user's home directory without warning about file permissions or credential sensitivity. If the host is multi-user, backed up insecurely, or compromised by other local malware/processes, these credentials can be exfiltrated and reused to access the trading APIs or impersonate the user/account.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill declares no explicit tool scope or allowed-tools despite documenting capabilities that require network access and local file reads/writes (configuration and token storage). Without a least-privilege declaration, an agent may grant broader access than users expect, increasing the blast radius if the skill is misused or compromised. In a finance/trading context, this is more sensitive because network calls and local credential/token storage can affect account integrity and expose authentication material.

Description-Behavior Mismatch

Medium
Confidence
84% confidence
Finding
The manifest scope focuses on 实盘交易能力 such as account management, fund lookup, subscriptions/redemptions, and asset queries. At L043 and in cmd_recommend, the skill additionally contacts a separate external recommendation service to retrieve marketing-style recommendation content, which is not clearly implied by the stated trading-tool description.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
Registration silently stores and exposes sensitive client credentials without warning, increasing the chance users handle or share them insecurely. In a real-money trading context, these credentials can authorize API actions and expose account and asset data, so casual disclosure materially raises security risk.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The manifest description, headings, and operational instructions are predominantly in Chinese, and the file does not indicate that users can choose another language or locale. This can violate language/locale policy where skills should not force a specific language without explicit opt-in or documented justification.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
The module docstring, examples, help text, and runtime messages are all presented only in Chinese, with no opt-in or language selection mechanism. This is a natural-language policy issue when a skill imposes a specific language or locale without giving the user a choice.

Static analysis

No suspicious patterns detected.