Back to skill

Security audit

Broadcast Sign Transfer

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says, but it handles real wallet keys and irreversible transfers with unsafe defaults and sensitive logging that users should review before installing.

Only install this if you understand it can move funds from the configured wallet. Use a low-balance dedicated wallet, avoid storing private keys in shell startup files, avoid running it in shared or logged environments, inspect transactions before broadcasting, and remove or disable debug logging of signed transactions and OKX signatures.

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 (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/broadcast_sign_transfer.py:237
Finding
Sensitive API authorization and signed transaction material exposed through debug logging<![CDATA[ ## Vulnerability Details **File Location**: `scripts/broadcast_sign_transfer.py`, lines 237–251, 384, and 436 **Vulnerability Type**: Sensitive data exposure through application logs **Risk Level**: High ### Vulnerable Code ```python def _okx_headers(self, method: str, path: str, body: str = "") -> dict: timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" sign = self._okx_sign(timestamp, method, path, body) print(f" [DEBUG] timestamp: {timestamp}") print(f" [DEBUG] method: {method}") print(f" [DEBUG] path: {path}") print(f" [DEBUG] body: {body}") print(f" [DEBUG] sign: {sign}") return { "OK-ACCESS-KEY": str(self.api_key), "OK-ACCESS-SIGN": str(sign), "OK-ACCESS-PASSPHRASE": str(self.passphrase), "OK-ACCESS-TIMESTAMP": str(timestamp), "Content-Type": "application/json", } ``` The signed transactions are also printed by both transfer operations: ```python signed_tx = self._sign_native_tx(to_address, amount_wei) print(f" signed_tx: {signed_tx}") return self._broadcast(signed_tx, enable_mev_protection) ``` ```python signed_tx = self._sign_token_tx(token_address, to_address, amount_raw) print(f" signed_tx: {signed_tx}") return self._broadcast(signed_tx, enable_mev_protection) ``` ### Technical Analysis The Skill writes the complete OKX request body, timestamp, request path, request method, HMAC authorization signature, and raw signed transaction to standard output. The Base64 operation used to produce the OKX signature is ordinary encoding of an HMAC-SHA256 digest and is not, by itself, a covert exfiltration mechanism. The security problem is that the encoded signature and every input needed to reproduce the authenticated request are printed together. The request body includes the wallet address and signed transaction. The raw signed transaction does not expose the wallet private key and cannot be modified ...[truncated 1672 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all production logging of: - Raw signed transactions - HMAC signatures - Authentication headers - Complete request bodies - API credentials or passphrases 2. If troubleshooting output is required, make it explicitly opt-in through a debug flag that defaults to disabled. 3. Apply structured redaction before logging. Log only non-sensitive operational fields such as chain name, transaction hash after acceptance, and a generated local correlation ID. 4. Ensure CI, agent, and application logs have restricted access and short retention periods. 5. Rotate the OKX API credentials if these logs may already have been exposed. 6. Add automated tests that capture stdout and verify that signatures, signed transactions, API keys, and passphrases never appear. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:160
Finding
Documentation instructs users to persist a wallet private key in a plaintext shell startup file<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 160–166 **Vulnerability Type**: Insecure plaintext storage of wallet credentials **Risk Level**: High ### Vulnerable Documentation ```bash export WALLET_PRIVATE_KEY="0x你的私钥" export OKX_ACCESS_KEY="你的Key" export OKX_SECRET_KEY="你的Secret" export OKX_PASSPHRASE="你的Passphrase" ``` ```bash source ~/.zshrc ``` ### Technical Analysis The documented setup procedure tells users to place the wallet private key and OKX credentials in `~/.zshrc` so that they persist across shell sessions. A shell startup file is plaintext configuration rather than a secure secret store. Although the documentation later warns that `~/.zshrc` is plaintext, the recommended default still creates a long-lived private-key copy. The Skill only needs access to the key while signing a transaction; persistent shell-wide exposure exceeds that minimum requirement. Shell startup files can be read by processes running as the same user and may be captured by workstation backups, configuration synchronization tools, diagnostic archives, support bundles, endpoint malware, or accidental repository commits. Exporting the variables also makes the secrets available to subsequently launched child processes. ### Attack Path 1. A user follows the installation instructions and adds the wallet private key and OKX credentials to `~/.zshrc`. 2. The credentials remain on disk indefinitely and are exported into future shell environments. 3. A malicious or compromised same-user process, backup system, synchronization service, diagnostic tool, or unauthorized local user obtains the file or process environment. 4. The attacker extracts `WALLET_PRIVATE_KEY`. 5. The attacker independently signs arbitrary transactions and transfers wallet assets to an attacker-controlled address. 6. The attacker may also use the exposed OKX credentials within their assigned permissions. ### Impact Assessment Compromise of the wallet private key grants complet ...[truncated 473 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the recommendation to store wallet private keys or API secrets in `~/.zshrc`, `.bashrc`, shell history, source files, or other plaintext configuration. 2. Prefer a hardware wallet or external signer so that the private key never enters the Python process. 3. Where local software signing is unavoidable, retrieve secrets from an operating-system keychain, encrypted secret manager, or dedicated wallet keystore. 4. Inject credentials only into the specific process that needs them and only for the duration of the operation. 5. Use a dedicated low-value wallet with the minimum funds necessary for the transfer workflow. 6. Configure OKX credentials with the narrowest available API permissions and rotate them periodically. 7. Document secure cleanup and credential-rotation procedures for users who previously followed the plaintext-storage instructions. ]]>

T08 · Insecure Dependencies

Warning
Location
SKILL.md:264
Finding
Security-sensitive dependencies are installed without version or integrity pinning<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, line 264 **Vulnerability Type**: Unpinned third-party dependency installation **Risk Level**: Medium ### Vulnerable Documentation ```bash pip3 install requests web3 ``` ### Technical Analysis The installation command resolves the latest available versions of `requests`, `web3`, and their transitive dependencies from the user's configured Python package index. It does not constrain versions, verify package hashes, or define a reviewed dependency graph. These dependencies execute in the same Python process that reads the wallet private key and OKX credentials. A malicious or compromised dependency would therefore inherit access to all process secrets and could alter transaction construction, signing inputs, RPC responses, or network requests. The audit found no typosquatted package name or explicitly malicious package in the project. The weakness is the absence of reproducibility and integrity controls around a security-critical supply chain. ### Attack Path 1. A user runs the documented unpinned installation command. 2. `pip` resolves mutable package versions and transitive dependencies from the configured index or mirror. 3. A compromised release, package index, mirror, or transitive dependency is installed. 4. The package executes when imported by the transfer script. 5. Malicious dependency code reads environment credentials, captures the wallet private key, changes recipient or amount handling, or transmits sensitive data externally. 6. Stolen wallet credentials can subsequently be used to authorize arbitrary transactions. ### Impact Assessment Successful dependency compromise would execute code with the privileges of the user running the Skill. Within the Skill process, it could access the wallet private key, OKX credentials, transaction contents, local files available to that user, and network connectivity. This could result in wallet takeover, credential theft, unauthorized tran ...[truncated 180 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define reviewed direct and transitive dependency versions in a lock file. 2. Pin exact versions rather than open-ended package names. 3. Record and enforce package hashes, for example with a requirements file installed using `pip --require-hashes`. 4. Install dependencies in an isolated virtual environment. 5. Document the expected trusted package index and prevent unintended fallback to untrusted mirrors. 6. Use automated dependency scanning and update dependencies through a reviewed change process. 7. Consider generating a software bill of materials and verifying package provenance in release workflows. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/broadcast_sign_transfer.py:359
Finding
Floating-point arithmetic can produce incorrect irreversible transfer amounts<![CDATA[ ## Vulnerability Details **File Location**: `scripts/broadcast_sign_transfer.py`, lines 359–378 and 392–420 **Vulnerability Type**: Financial precision and numeric truncation error **Risk Level**: Medium ### Vulnerable Code Native-token transfers accept a binary floating-point value and convert it to wei: ```python def transfer_native( self, to_address: str, amount: float, enable_mev_protection: bool = False, ) -> BroadcastResult: """ Transfer native tokens. """ if not to_address or not to_address.startswith("0x"): raise ValueError("to_address format error") if amount <= 0: raise ValueError("amount must be greater than 0") amount_wei = self.w3.to_wei(amount, "ether") ``` ERC-20 transfers multiply a floating-point amount and truncate it to an integer: ```python def transfer_token( self, token_address: str, to_address: str, amount: float, enable_mev_protection: bool = False, ) -> BroadcastResult: """ Transfer ERC20 tokens. """ if not token_address or not token_address.startswith("0x"): raise ValueError("token_address format error") if not to_address or not to_address.startswith("0x"): raise ValueError("to_address format error") if amount <= 0: raise ValueError("amount must be greater than 0") contract = self.w3.eth.contract( address=Web3.to_checksum_address(token_address), abi=ERC20_ABI, ) decimals = contract.functions.decimals().call() symbol = contract.functions.symbol().call() amount_raw = int(amount * (10 ** decimals)) ``` ### Technical Analysis Python `float` uses binary floating-point representation and cannot exactly represent many decimal financial values. Multiplication by a token's decimal scale can therefore result in a value slightly above or below the intended integer amount. For ERC-20 transfers, `int()` truncates rather than performing an explicit, validated roundi ...[truncated 1311 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Accept transfer amounts as decimal strings instead of `float`. 2. Parse values with Python's `decimal.Decimal`. 3. Validate that the amount has no more fractional digits than the asset supports. 4. Convert to base units using exact decimal arithmetic and require an integral result. 5. Reject scientific notation, non-finite values, and values outside explicit minimum and maximum limits unless deliberately supported. 6. Change CLI arguments from `type=float` to strings and perform centralized validated conversion. 7. Display the exact base-unit and human-readable amount for user confirmation before signing. 8. Add test cases for values such as `0.1`, very small token units, maximum supported precision, excess precision, and large amounts. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (7)

Missing User Warnings

High
Confidence
98% confidence
Finding
The public transfer methods sign and broadcast irreversible on-chain transactions immediately once called, with no explicit confirmation, review step, transaction preview, or policy gate. In a skill that holds a private key and can move blockchain assets, this is especially dangerous because any accidental invocation, prompt injection in a larger agent workflow, parameter tampering, or misuse can directly cause unrecoverable loss of funds.

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill explicitly requires environment secrets such as a wallet private key and OKX API credentials and describes network-based transaction broadcasting, but it does not declare any tool scope or permission boundaries. In an agent setting, this omission can lead to overbroad access to sensitive environment variables and outbound network actions without transparent authorization, which is especially dangerous because the skill performs irreversible blockchain transfers.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
User-facing documentation, error messages, and CLI help throughout the file are presented in Chinese, with no indication that the user can select another language. This creates a language/locale policy issue because the skill effectively imposes one language without opt-in or justification.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The script accesses a wallet private key and exchange API credentials directly from environment variables, which gives the skill the ability to sign and broadcast real asset transfers. In this skill context, that capability is expected for functionality, but it is still highly sensitive because any misuse, logging, process compromise, or untrusted invocation path can lead to immediate theft or unauthorized transactions.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The code relies on highly sensitive private-key and API-key material without prominent in-code warnings or protective handling guidance, despite enabling direct financial operations. In this context, poor operator awareness materially raises the chance of unsafe deployment, credential leakage, or use in an untrusted runtime.

Intent-Code Divergence

Low
Confidence
98% confidence
Finding
The module docstring instructs users to import `BroadcastTransaction` from `broadcast_transaction`, but this file actually defines the implementation in `broadcast_sign_transfer.py`. This is an active documentation/code inconsistency that misstates how the skill is used.

Context-Inappropriate Capability

Low
Confidence
85% confidence
Finding
The manifest describes a skill for constructing, signing, and broadcasting native token and ERC20 transfers. However, the embedded ERC20 ABI also includes the `allowance` read method, which enables approval/authorization inspection even though no approval flow or spender-based transfer behavior is part of the declared purpose.

Static analysis

No suspicious patterns detected.