T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/degov-client.ts:9
- Finding
- Automatic x402 payments can be authorized for an unrestricted API origin without a local spending limit<![CDATA[ ## Vulnerability Details **File Location**: `scripts/degov-client.ts`, lines 9 and 81-114 **Vulnerability Type**: Unrestricted payment endpoint and missing transaction policy **Risk Level**: High ### Vulnerable Code ```ts const API_BASE_URL = process.env.DEGOV_AGENT_API_BASE_URL || 'https://agent-api.degov.ai'; ``` ```ts async function getPaymentClient(): Promise<{ accountAddress: `0x${string}`; fetchWithPayment: typeof fetch; }> { const { account } = await getAccount(); const publicClient = createPublicClient({ chain: base, transport: http('https://mainnet.base.org'), }); const signer = toClientEvmSigner(account, publicClient); return { accountAddress: account.address, fetchWithPayment: wrapFetchWithPaymentFromConfig(fetch, { schemes: [ { network: 'eip155:8453', client: new ExactEvmScheme(signer), }, ], }), }; } async function apiCall(endpoint: string): Promise<unknown> { const { accountAddress, fetchWithPayment } = await getPaymentClient(); const url = `${API_BASE_URL}${endpoint}`; console.error(`Using wallet: ${accountAddress}`); console.error(`Calling: ${url}`); const response = await fetchWithPayment(url); const paymentResponse = response.headers.get('PAYMENT-RESPONSE'); const text = await response.text(); ``` ### Technical Analysis The paid API client decrypts the locally stored wallet key, constructs an EVM signer, and gives that signer to the x402-enabled fetch wrapper. The destination is derived from `DEGOV_AGENT_API_BASE_URL`, which can contain an arbitrary origin. The implementation does not locally enforce: - An allowlist of trusted API hosts. - HTTPS for non-local endpoints. - An expected x402 payment recipient. - An expected USDC contract or payment asset. - A maximum amount per request. - A cumulative session or daily budget. - Interactive confirmation of the exact payment terms. Network transmission of signed x402 payment autho ...[truncated 2071 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Restrict the default paid client to an explicit origin allowlist containing `https://agent-api.degov.ai`. 2. Reject non-HTTPS alternate origins, except an explicitly enabled loopback development mode. 3. Require a separate, clearly named unsafe-development flag before honoring `DEGOV_AGENT_API_BASE_URL`. 4. Validate every x402 challenge before signing: - Require Base Mainnet, chain ID 8453. - Require the intended USDC contract. - Require an approved payment recipient. - Reject unsupported schemes, assets, networks, and facilitators. 5. Add an enforceable maximum payment amount per request. 6. Add cumulative session and daily spending limits stored independently from server-provided pricing. 7. Show the exact recipient, token, network, and amount before signing. Require user confirmation unless the payment falls within a previously approved capped budget. 8. Fail closed when pricing metadata is unavailable for a paid operation rather than relying on informational fallback prices as a security boundary. 9. Add tests confirming that unapproved origins, recipients, assets, and excessive payment amounts are rejected before any authorization is generated. ]]>
