Every x402 project fails npm audit
Run npm audit in any x402 seller or buyer today and it comes back red: a high advisory in zod, reached through @x402/core, @x402/evm, @x402/extensions, @x402/mcp, @coinbase/x402 and @coinbase/cdp-sdk. The advice npm prints next to it would break your payments. We read where x402's own code actually uses zod, and measured what the bug does.
What the advisory is
When zod validates an array and many of its items fail, it keeps one issue object for every failing item, with no limit and no early stop. A large enough array of bad items exhausts the process's memory and crashes it. The bug was reported in 2023 (zod#1872) and fixed in zod 4.6.6; the advisory followed on 1 October 2026. Zod 3 gets no fix.
We measured it with the zod 3.25.76 that x402 installs, using @x402/core's own PaymentRequired schema and an accepts array of zeros:
| Items in the array | JSON size | Memory used | Time |
|---|---|---|---|
| 10,000 | 20 KB | 4 MB | 33 ms |
| 100,000 | 0.2 MB | 39 MB | 121 ms |
| 500,000 | 1.0 MB | 152 MB | 0.8 s |
| 1,000,000 | 2.0 MB | 309 MB | 1.8 s |
About 150 bytes of memory for every byte sent. Two megabytes is enough to take down a 512 MB server, the size of many small hosting plans.
Where x402 runs zod
The table above only matters where outside data reaches a zod array schema. In @x402/core 2.28.0 we found one such place on the paid path:
- The buyer's payment header (
PAYMENT-SIGNATURE) is decoded withJSON.parse, not validated with zod. Node also caps all request headers at 16 KB, which in the table is under 3 MB of memory even if it were. - A seller's 402, on the buyer's side:
@x402/fetchreads thePAYMENT-REQUIREDheader or the v1 body withJSON.parseand does not run zod on it. - The facilitator's answers to verify and settle are validated with zod. That data comes from the facilitator you configured yourself, such as Coinbase's CDP facilitator, not from buyers.
So x402 itself gives a buyer or a seller no way to send you an oversized array that zod then chews on. The audit warning is real, but it isn't a hole in your payment flow.
Why npm audit fix makes it worse
npm's suggested fix is to "downgrade" @coinbase/x402 to 0.0.0, @x402/evm, /svm, /express and /extensions to 0.0.1, and mppx to 0.8.19. @coinbase/x402 0.0.0 is a two-file "placeholder package" and @x402/evm 0.0.1 holds three files; mppx 0.8.19 is a much older release. npm audit fix --force installs them and payments stop working. Plain npm audit fix, without --force, doesn't touch them and still fixes the advisories that do have a fix (on 26 October 2026 that included body-parser, follow-redirects and undici).
Where the risk really is: your own zod 3
Many x402 servers use zod themselves to check request bodies, and the same package resolves to zod 3 through x402. An array in your schema and a body you didn't cap is exactly the table above. Three things close it:
- Cap request bodies.
express.json({ limit: "100kb" })or smaller; Express's default is 100 KB, but many apps raise it. Our own services cap bodies at 4 to 256 KB per route. - Don't count on
.max()in zod 3. We triedz.array(z.string()).max(100)on a million bad items: zod 3 still checked every item and used 280 MB. Check the length yourself before zod sees it, for exampleArray.isArray(v) && v.length > 100→ reject. - Use zod 4.6.6 or later in your own code. Add
"zod": "^4.6.6"to your own dependencies; x402 keeps its own zod 3 copy, and your code gets the fixed one.
Facilitator operators receive verify and settle requests from other people's servers. If they validate those bodies with zod 3, the same advice applies to them.
When it goes away
The warning disappears once the x402 packages accept zod 4. On 26 October 2026 the latest versions still required zod 3:
| Package | Version | zod |
|---|---|---|
| @x402/core, /evm, /extensions, /mcp | 2.28.0 | ^3.24.2 |
| @coinbase/x402 | 2.1.0 | ^3.24.2 |
| @coinbase/cdp-sdk | 1.60.0 | ^3.25.76 |
| x402, x402-express (v1) | 1.2.0 | ^3.24.2 |
| mppx | 0.15.0 | ^4.6.5 (resolves to the fixed 4.6.6+) |
We asked Coinbase to move cdp-sdk to zod 4, or to accept ^3 || ^4 as abitype already does, in coinbase/cdp-sdk#863. Our services keep a weekly audit issue open that lists only zod 3 and the packages that pull it in, so a new advisory stands out at once.
How we checked
- Advisory data from the npm advisory API and OSV (GHSA-mrhx-c7xc-m3w5, CVE-2023-54404), on 26 October 2026.
- Dependency ranges from the npm registry's latest manifests of each package.
- The zod calls read in the published code of
@x402/core(client, server, HTTP and schema bundles) and@x402/fetch. - The memory numbers:
@x402/core'sparsePaymentRequiredon anacceptsarray of N zeros, zod 3.25.76, Node 24, heap measured before and after one call.
Questions
Is my x402 server vulnerable because npm audit says high?
Not through x402 itself. In @x402/core 2.28.0 the only zod validation on the paid path is of the facilitator's answers to verify and settle, from the facilitator you configured. The payment header a buyer sends is decoded with JSON.parse, not zod, and Node limits all headers to 16 KB anyway. What can hurt you is zod 3 in your own code: an array schema without a maximum, fed a request body you didn't cap.
Should I run npm audit fix?
Not with --force. npm's suggested fix for this advisory is to move @coinbase/x402 to 0.0.0, @x402/evm, /svm, /express and /extensions to 0.0.1, and mppx to 0.8.19: old or empty releases. Payments stop working. Plain npm audit fix (without --force) is safe and fixes the other advisories it can.
When does the warning go away?
When @x402/core, @coinbase/x402 and @coinbase/cdp-sdk accept zod 4 (4.6.6 or later), or ^3 || ^4 as abitype already does. On 26 October 2026 the latest versions all still required zod 3. We asked Coinbase in coinbase/cdp-sdk#863.
What should I do in my own code?
Cap request bodies (express.json({ limit: '100kb' }) or smaller), check the length of arrays from callers before zod 3 sees them (its .max() still checks every item), and move your own code to zod 4.6.6 or later; zod 3 and zod 4 can sit side by side in one project.
Check an x402 endpoint before you pay it with x402 Doctor, and a transaction before you sign it with presign-guard.