T09 · Insecure Skill Coding Practices
- Location
SKILL.md:39- Finding
Payment Verification Without Settlement Allows Replayed Paid Access
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 39–50
Vulnerability Type: Payment authorization replay / incomplete payment enforcement
Risk Level: HighVulnerable Code
python payload = json.loads(base64.b64decode(x_payment).decode()) r = httpx.post("https://x402.org/facilitator/verify", json={ "x402Version": 1, "paymentPayload": payload, "paymentRequirements": REQUIREMENTS, }, timeout=15) if not r.json().get("isValid"): return JSONResponse(status_code=402, content={"error": "payment invalid"}) return JSONResponse(content=do_the_work(await request.json()))Technical Analysis
The documented endpoint treats a successful response from the facilitator's verification operation as sufficient authorization to execute the paid service. It does not settle the payment, record a consumed authorization identifier or nonce, or otherwise enforce one-time use before calling
do_the_work.The remote caller controls the base64-encoded payment payload supplied through the
X-PAYMENTHTTP header. Once the caller obtains a valid signed payment authorization, the same payload can be submitted repeatedly while it remains valid. Because the implementation only verifies the authorization and has no local replay protection, repeated requests can pass the paid-access check without evidence that a distinct payment was settled for each invocation.This crosses the endpoint's payment authorization boundary: an unauthenticated remote client receives per-call functionality based on a reusable authorization rather than a uniquely settled payment.
Attack Path
- A remote client requests the paid endpoint and receives the HTTP 402 payment requirements.
- The client creates one valid signed payment authorization satisfying those requirements.
- The client submits that authorization in the
X-PAYMENTheader. - The facilitator reports the payload as valid, and the endpoint executes ...[truncated 864 chars]
- Remediation
View remediation
Remediation Suggestions
- Settle every verified payment through the facilitator before invoking
do_the_work, and grant access only after receiving an authenticated successful settlement response. - Enforce one-time use by recording a unique authorization identifier or nonce in durable storage and atomically rejecting duplicates.
- Validate the settled payment against the exact expected recipient, network, asset, amount, scheme, and validity window rather than relying only on a generic validity flag.
- Bind each accepted payment to the relevant request or operation where the protocol supports such binding.
- Make settlement and replay-state updates atomic so concurrent submissions of the same authorization cannot both execute.
- Design retry and idempotency handling so network failures do not result in either unpaid execution or duplicate paid work.
- Fail closed on malformed or unexpected facilitator responses, including non-success HTTP status codes, invalid JSON, missing fields, and timeouts.
- Settle every verified payment through the facilitator before invoking
