T09 · Insecure Skill Coding Practices
- Location
SKILL.md:63- Finding
Unvalidated Remote Payment Authorization
- Content
View full analysis
unpaid.headers.get(name), {}, ); const paymentPayload = await httpClient.createPaymentPayload(required); const paid = await fetch(endpoint, { method: "POST", headers: { "content-type": "application/json", ...httpClient.encodePaymentSignatureHeader(paymentPayload), }, body: JSON.stringify(payload), }); ``` ### Technical Analysis The API origin can be changed through environment variables. After the selected server returns an HTTP 402 response, the example passes the server-controlled payment requirements directly to `createPaymentPayload` and signs them using the account derived from `EVM_PRIVATE_KEY`. The example does not explicitly validate critical payment properties before signing, including: - Recipient address - Network or chain identifier - Token or asset - Maximum payment amount - Expiration time - Nonce or replay constraints - Whether the payment terms correspond to the expected service Although the x402 library may perform protocol-level validation, protocol validity is not equivalent to authorization under the user's local payment policy. A syntactically valid payment request can still name an unexpected recipient or request an unacceptable amount. ### Attack Path 1. An attacker compromises the configured API service, alters `X402_API_BASE_URL` or `API_BASE_URL`, or otherwise causes the client to communicate with an attacker-controlled endpoint. 2. The malicious endpoint responds to the initial request with HTTP 402 and attacker-selec ...[truncated 1172 chars]- Remediation
View remediation
