T09 · Insecure Skill Coding Practices
Error
- Location
- esim_api.py:190
- Finding
- Unvalidated Remote Payment Parameters Can Redirect or Alter USDC Transactions## Vulnerability Details **File Location**: `esim_api.py:190-231` **Vulnerability Type**: Failure to validate security-critical payment parameters **Risk Level**: High ### Vulnerable Code ```python data = response.json() # Parse x402 response - find the "transfer" scheme accepts_list = data.get("accepts", []) accepts = None for scheme in accepts_list: if scheme.get("scheme") == "transfer": accepts = scheme break # Fallback to first scheme if transfer not found if accepts is None: accepts = accepts_list[0] if accepts_list else {} extra = accepts.get("extra", {}) amount_raw = accepts.get("amount", 0) if isinstance(amount_raw, str): amount_raw = int(amount_raw) # Get network info from response network = accepts.get("network", self.config["caip2"]) chain_id = accepts.get("extra", {}).get("chainId", self.config["chain_id"]) return PaymentRequired( nonce=extra.get("nonce", ""), amount_raw=amount_raw, amount_usdc=amount_raw / 1_000_000, pay_to=accepts.get("payTo", ""), asset=accepts.get("asset", ""), network=network, chain_id=chain_id, ) ``` The associated workflow in `SKILL.md:248-252` explicitly directs the caller to use the remotely supplied recipient: ```markdown **Important**: Always use the `payTo` address from the 402 response. Never hardcode payment addresses. ``` ### Technical Analysis The client accepts the recipient address, payment amount, asset contract, network, chain ID, and nonce directly from the remote HTTP 402 response. It does not enforce that: - `network` equals the configured CAIP-2 network. - `chain_id` equals the configured Base Mainnet or Base Sepolia chain ID. - `asset` equals the ...[truncated 2488 chars]
- Remediation
- ## Remediation Suggestions 1. Require an explicit `transfer` scheme and reject the response if none is present. Remove the fallback to the first entry. 2. Validate `network` and `chainId` against the selected entry in `NETWORK_CONFIG`; do not use remote values to override local network selection. 3. Compare `asset` case-insensitively with the configured USDC contract for the selected network. 4. Validate `payTo` and `asset` as 20-byte hexadecimal EVM addresses before presenting transaction instructions. 5. Parse USDC values with `Decimal` or integer smallest units instead of binary floating-point arithmetic. 6. Bind the payment response to the selected package and prior quote. Require the 402 amount to exactly equal the user-confirmed amount. 7. Validate the nonce format and ensure it belongs to the current purchase attempt. 8. Reject missing, zero, negative, malformed, or unexpectedly large payment amounts. 9. Require renewed user confirmation if any payment parameter differs from the previously displayed transaction details. 10. Before signing, display and independently verify the final recipient, token contract, chain, and amount. Wallet policy should enforce spending limits and an allowlist where operationally possible. 11. After payment, verify the transaction receipt, successful token transfer event, recipient, token contract, amount, and chain before submitting the transaction hash as proof.
