Skip to content

fix(x402): strip extensions/resource from paymentPayload before facilitator (parity with node 2.7.5) - #92

Merged
vvillait88 merged 2 commits into
mainfrom
fix/x402-strip-unsigned-payload-fields
Jul 18, 2026
Merged

fix(x402): strip extensions/resource from paymentPayload before facilitator (parity with node 2.7.5)#92
vvillait88 merged 2 commits into
mainfrom
fix/x402-strip-unsigned-payload-fields

Conversation

@vvillait88

Copy link
Copy Markdown
Contributor

Parity with node-commerce 2.7.5

x402 clients echo the 402 challenge's extensions (Bazaar input schema) + resource into the payload alongside the signed payload + accepted. The Coinbase facilitator's /x402/verify validates the payment payload against its x402V2PaymentPayload schema, which is { x402Version, payload, accepted } and admits neither extensions nor resource: their presence makes the payload match no union branch (must match one of [x402V2PaymentPayload, x402V1PaymentPayload]) and settle fails. Routes with a large echoed Bazaar schema fail while small ones slip through.

Fix

process_x402_settle now runs strip_unsigned_x402_payload_fields before coercing to the typed model whose model_dump(by_alias, exclude_none) reaches the facilitator, dropping only extensions + resource and keeping accepted (which CDP requires, and which verify_x402_request reads for network/payTo). Neither stripped block is part of the EIP-3009 signature.

Confirmed against the live CDP facilitator: the stripped accepted-nested payload passes schema and reaches signature verify; a flat { x402Version, scheme, network, payload } is rejected with requires 'accepted'.

Tests

Unit: drop-both / keep-accepted, unchanged-when-absent (same object), single-field strip, non-dict passthrough. Integration: process_x402_settle forwards a payload to BOTH verify and settle with accepted kept and extensions/resource gone.

Full suite green (1840 passed, 95.36% coverage), ruff + ty clean.

🤖 Generated with Claude Code

vvillait88 and others added 2 commits July 17, 2026 20:01
…litator call

Mirrors node-commerce 2.7.5. x402 clients echo the 402 challenge's `extensions`
(Bazaar input schema) + `resource` into the payload alongside the signed
`payload` + `accepted`. The Coinbase facilitator's /x402/verify validates the
payment payload against its x402V2PaymentPayload schema, which is
{x402Version, payload, accepted} and admits neither extensions nor resource:
their presence makes the payload match no union branch and settle fails
("must match one of [x402V2PaymentPayload, x402V1PaymentPayload]"). Routes with
a large echoed schema fail while small ones slip through.

process_x402_settle now runs strip_unsigned_x402_payload_fields before coercing
to the typed model whose model_dump reaches the facilitator, dropping only
extensions + resource and keeping accepted (which CDP requires, and which
verify_x402_request reads for network/payTo). Confirmed against the live CDP
facilitator: the stripped accepted-nested payload passes schema and reaches
signature verify. Bump to 2.5.10.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vvillait88
vvillait88 merged commit eef3dfe into main Jul 18, 2026
7 checks passed
@vvillait88
vvillait88 deleted the fix/x402-strip-unsigned-payload-fields branch July 18, 2026 03:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant