fix(x402): enforce cap on selected payment requirement - #2272
Merged
Merged
Conversation
🦋 Changeset detectedLatest commit: c8fd906 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
|
✅ agents import sizes: no significant changes ( |
mattzcarey
force-pushed
the
fix/x402-payment-modernization
branch
from
September 14, 2026 15:43
e208f73 to
838a5f0
Compare
agents
@cloudflare/ai-chat
@cloudflare/codemode
hono-agents
@cloudflare/shell
@cloudflare/think
@cloudflare/voice
@cloudflare/worker-bundler
commit: |
Non-exact schemes and malformed amounts return the server's original 402 result again, amounts parse with BigInt as before, and the structuredClone snapshot and its ordering-dependent test are removed.
A retained reference could change a requirement between the cap check and signing. Also pin the before-payment hook in the mocked suite.
…ents A shallow copy still shared nested fields such as extra, which feeds the signed EIP-712 domain. structuredClone makes the callback's copies fully independent of what is cap-checked and signed.
mattzcarey
force-pushed
the
fix/x402-payment-modernization
branch
from
September 28, 2026 14:26
3cf2319 to
1e63381
Compare
A non-exact offer followed by an exact offer on a network the EVM client cannot sign used to reach payload creation and come back as a generic 'Failed to create payment payload', dropping the server's payment options. x402 selects a requirement before it runs any hook, so a payment request that fails without reaching the cap hook offered nothing this client can sign: return the original 402 for it, as the old first-requirement check did. This replaces the scheme === 'exact' pre-check with x402's own selection. Also snapshot the advertised requirements once, so what is cap-checked and signed is a copy that nothing else aliases.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
withX402ClientcheckedmaxPaymentValueagainst the first advertised payment requirement, but x402 picks the requirement it signs afterwards, after applying scheme support and network preference. A server could advertise a cheap first offer on a network the client doesn't prefer and a second, expensive one it does. The client would then sign the expensive one without the cap ever applying to it.The cap now runs in x402's pre-signing hook, on the requirement that will actually be signed:
beforePaymentCreationhooks outside its owntry, from 2.0.0 onwards, so the typed errors reachwithX402Clientunchanged across the whole@x402/core ^2.0.0peer range. Returning{ abort: true }would have been rewrapped as a plainError.Payment exceeds client cap: …without signing or retrying. A malformed, negative or non-exactselection returns the server's original 402 result, as before.exactoffer, or only ones on networks the EVM client can't sign), the original 402 comes back with the server's payment options. x402 selects before it runs any hook, so a request that fails without reaching the cap hook is exactly that case.