T09 · Insecure Skill Coding Practices
Error
- Location
- src/index.ts:9
- Finding
- Unauthenticated and Replayable Billing Requests## Vulnerability Details **File Location**: `src/index.ts`, lines 9-24 **Vulnerability Type**: Missing authentication, authorization, and replay protection on a billing operation **Risk Level**: High ### Vulnerable Code ```ts if (request.method !== "POST") { return Response.json({ error: "POST required" }, { status: 405 }); } const body = await request.json() as { user_id: string }; if (!body.user_id) { return Response.json({ error: "user_id required" }, { status: 400 }); } const billing = await chargeUser({ userId: body.user_id, apiKey: env.SKILLPAY_API_KEY, priceUsdt: 0.03, skillName: "sea-whatsapp-business-bot", }); if (!billing.success) { ``` ### Technical Analysis The public request handler accepts an arbitrary caller-provided `user_id` and immediately passes it to the privileged billing function. The only validation is that the identifier is non-empty. The handler does not authenticate the caller, verify that the caller owns or is authorized to bill the supplied identifier, require a signed request, enforce an idempotency key, or implement visible replay and rate-limiting controls. Consequently, possession or discovery of another user's identifier may be sufficient to request charges against that user. The unavailable `../../shared/billing` implementation might contain additional safeguards, but no such protection is established by the supplied project. Security controls inside that dependency therefore cannot be relied upon or verified in this audit. ### Attack Path 1. An attacker discovers or guesses a valid user identifier. 2. The attacker sends a request to the public `/respond` endpoint: ```http POST /respond Content-Type: application/json {"user_id":"victim-user-id"} ``` 3. The handler accepts the identifier without authenticating the requester or checking ownership. 4. The Worker invokes `chargeUser` using its server-side `SKILLPAY_API_KEY`. ...[truncated 751 chars]
- Remediation
- ## Remediation Suggestions - Authenticate every caller before permitting a billing operation. - Derive the billing identity from the authenticated principal instead of trusting a caller-supplied `user_id`. - If an identifier must be submitted, cryptographically bind it to the authenticated session and verify authorization server-side. - Require signed requests with a short expiration time and a unique nonce. - Require an idempotency key for each legitimate invocation and persist its result so retries cannot cause duplicate charges. - Apply per-account and per-source rate limits, spending limits, and anomaly detection. - Return an appropriate authorization error when identity verification fails. - Verify that `chargeUser` independently validates authorization and prevents duplicate charges. - Add tests covering forged identifiers, repeated requests, expired signatures, duplicate idempotency keys, and concurrent replay attempts.
