T09 · Insecure Skill Coding Practices
Error
- Location
- skill.md:73
- Finding
- Blind Signing of Server-Controlled USDC Payment Authorization<![CDATA[ ## Vulnerability Details **File Location**: `skill.md:73-84` **Vulnerability Type**: Unvalidated cryptographic signing of remote payment data **Risk Level**: Critical ### Vulnerable Code ```javascript const res = await fetch("https://budsbase.xyz/api/prepare", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ wallet: wallet.address, challengeId: "CHALLENGE_ID", answer: "ANSWER" }), }); const { prepareId, payment } = await res.json(); // 2b. Sign USDC payment (EIP-712) const paymentSignature = await wallet.signTypedData(payment.domain, payment.types, payment.values); console.log(JSON.stringify({ prepareId, paymentSignature })); ``` ### Technical Analysis The remote `/api/prepare` endpoint controls all EIP-712 components passed to `wallet.signTypedData`: the domain, type definitions, and values. The Skill does not locally verify the following security-critical properties: - Base mainnet chain ID - Official Base USDC contract address - EIP-712 verifying contract - Authorization type and field layout - Payment recipient - Exact payment amount of 1 USDC - Authorization validity interval - Authorization nonce - Whether the authorization is limited to the advertised mint A statement elsewhere in the documentation that the payment is 1 USDC does not cryptographically enforce that constraint. Because an EIP-712 signature can authorize an on-chain token operation, signing arbitrary structured data supplied by a remote service crosses a financial trust boundary. ### Attack Path 1. An attacker compromises `budsbase.xyz`, its API infrastructure, DNS resolution, or another component capable of controlling the `/api/prepare` response. 2. The malicious endpoint returns altered EIP-712 data, such as a larger token amount, a different recipient, a different verifying contract, or another signing schema. 3. The Skill passes the response directly to `wallet.signTypedData` without validation or presenting decoded deta ...[truncated 747 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Do not sign EIP-712 data directly from a remote response. - Construct the expected authorization locally from independently verified inputs wherever possible. - Hard-code or securely pin the expected Base chain ID and official USDC contract address. - Allow only the exact expected EIP-712 primary type and field schema. - Verify the recipient against an audited, documented payment recipient. - Enforce an exact amount of 1 USDC using the token's correct decimal representation. - Enforce short and reasonable `validAfter` and `validBefore` bounds. - Validate the authorization nonce and reject reused or malformed values. - Decode and display the complete authorization to the user. - Require explicit user confirmation immediately before signing. - Prefer an external or hardware wallet that independently displays the typed-data details. - Abort on every unknown field, unexpected domain value, schema variation, or contract mismatch. ]]>
