T09 · Insecure Skill Coding Practices
- Location
SKILL.md:65- Finding
Payment Verification Bypass Accepts Forged Payment Headers
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 65–76
Vulnerability Type: Payment authorization bypass
Risk Level: HighVulnerable Code
javascript function checkPayment(req, res, path, method, price, description) { const paymentHeader = getPaymentHeader(req); if (!paymentHeader) { const reqs = buildPaymentRequirements(path, method, price); sendJSON(res, 402, { error: 'Payment required', paymentRequired: reqs }, { 'X-PAYMENT-REQUIRED': encodePaymentHeader(reqs) }); return null; } const payload = decodePaymentHeader(paymentHeader); if (!payload) { sendJSON(res, 400, { error: 'Invalid payment header' }); return null; } // Demo mode: accept any valid-looking payment // TODO: Enable facilitator verification in production return true; }Technical Analysis
The payment gate only Base64-decodes and JSON-parses the attacker-controlled
payment-signatureorx-paymentheader. Successful parsing is treated as proof of payment.The implementation does not verify:
- A cryptographic payment signature
- Payment settlement or transaction status
- The payer or intended recipient
- The required amount and asset
- The configured blockchain network
- The requested resource
- Payment expiration
- Nonce uniqueness or replay status
Consequently, any syntactically valid JSON value that parses to a truthy value can satisfy the payment check. For example, Base64-encoded
{}is accepted even though it contains no payment evidence.Attack Path
- An attacker identifies the protected
POST /api/your-serviceendpoint. - The attacker creates an arbitrary JSON object, such as
{}. - The attacker Base64-encodes it as
e30=. - The attacker sends
payment-signature: e30=orx-payment: e30=with the request. decodePaymentHeader()parses the forged payload successfully.checkPayment()returnstruewithout cryptographic or settlement verification.- The protected service executes without ...[truncated 646 chars]
- Remediation
View remediation
Remediation Suggestions
- Remove the permissive demo behavior from any publicly exposed deployment.
- Fail closed unless the payment has been cryptographically verified and confirmed as settled.
- Verify the signature, payer,
payTorecipient, exact amount, asset, network, resource, expiration, and protocol version. - Add nonce or transaction-identifier tracking to prevent payment replay.
- Build the expected payment requirements server-side; never trust requirements supplied by the client.
- Treat facilitator timeouts, malformed responses, non-success HTTP statuses, and parsing errors as failed authorization.
- Keep demonstration mode explicitly disabled by default and bind demonstration servers to localhost.
- Add automated tests confirming rejection of missing, malformed, forged, underpaid, wrong-recipient, wrong-network, expired, and replayed payments.
