T09 · Insecure Skill Coding Practices
- Location
scripts/lib/x402-pay.mjs:209- Finding
Remote Payment Challenge Is Signed Without Validating the Confirmed Amount, Recipient, Asset, or Network
- Content
View full analysis
a.scheme === 'exact') || accepts[0]; // ---------------------------------------------------------- // Step 2: Sign EIP-712 TransferWithAuthorization // // Mirrors @x402/evm ExactEvmScheme.createPaymentPayload() exactly: // - requirement.maxAmountRequired is ALREADY in atomic units // - requirement.asset is the USDC contract address (verifyingContract) // - requirement.network may be CDP format ("base") or CAIP-2 ("eip155:8453") // - requirement.extra.{name,version} provides EIP-712 domain params // ---------------------------------------------------------- const nonce = createNonce(); const now = Math.floor(Date.now() / 1000); // Amount is already in atomic units (e.g., "250000" = $0.25 USDC) const amount = requirement.maxAmountRequired || requirement.amount || '0'; const authorization = { from: account.address, to: getAddress(requirement.payTo), value: amount, validAfter: (now - 600).toString(), // 10 minutes before (matches SDK) validBefore: (now + (requirement.maxTimeoutSeconds || 3600)).toString(), nonce, }; // Derive EIP-712 domain from requirement fields const chainId = networkToChainId(requirement.network); const verifyingContract = getAddress(requirement.asset); if (!requirement.extra?.name || !requirement.extra?.version) { throw new Error('Payment requirement missing extra.name/version for EIP-712 domain'); } const domain = { name: requirement.extra.name, version: requirement.extra.version, chainId, verifyingContract, }; ``` The price displayed to the user comes from a separate local pricing table: ```js const rawPrice = PRICING[command] || '?'; const price ...[truncated 3957 chars]- Remediation
View remediation
