T09 · Insecure Skill Coding Practices
- Location
references/lifecycle-hooks.md:130- Finding
Bearer Token Can Be Forwarded to an Untrusted HTTP 402 Responder
- Content
View full analysis
{ const apiKey = process.env.API_KEY; if (apiKey) { return { headers: { "Authorization": `Bearer ${apiKey}` } }; } }); ``` ### Technical Analysis The example reads a bearer credential from the `API_KEY` environment variable and adds it to a retry whenever the client receives an HTTP 402 response. It does not demonstrate validation of the request destination, HTTPS scheme, expected credential audience, redirect chain, or an allowlisted origin before releasing the credential. An HTTP 402 response is controlled by the destination server. Consequently, any endpoint that the application or Agent is induced to request may trigger this hook. If the x402 client accepts arbitrary or externally supplied URLs, an attacker-controlled server can return a syntactically valid 402 response and cause the subsequent request to contain the bearer token. The `paymentRequired` value is also not used to ensure that credential fallback is appropriate for the destination. This behavior exceeds minimum privilege because a process-wide environment credential may be exposed to any responding origin rather than only to the service for which it was issued. ### Attack Path 1. The application or Agent is induced to request an attacker-controlled URL, or a trusted URL redirects to an attacker-controlled origin. 2. The attacker returns an HTTP 402 response that activates `onPaymentRequired`. 3. The hook reads `API_KEY` from the process environment. 4. The client retries the request with `Authorization: Bearer `. 5. The attacker records the authorization header. 6. The attacker reuses the token against services that accept it, subject to the token's p ...[truncated 544 chars]- Remediation
View remediation
{ const requestUrl = new URL(context.request.url); if (requestUrl.protocol !== "https:" || requestUrl.origin !== trustedOrigin) { return; } const apiKey = process.env.EXAMPLE_API_KEY; if (!apiKey) { return; } return { headers: { Authorization: `Bearer ${apiKey}`, }, }; }); ``` The surrounding HTTP client should additionally reject cross-origin redirects or strip the authorization header before following them. ]]>
