← minia2a

What Happens When Academics Stress-Test 15 x402 Payment Gateways: An Operator's Security Audit

August 9, 2026 · 12 min read · security research

Last week, researchers from EPFL, Zhejiang University, and USENIX Security 2026 dropped a paper that should make every x402 operator stop and audit their code: 31 security vulnerabilities across 15 facilitators, covering 99% of x402 transaction volume. Every single facilitator they tested violated at least one payment verification or settlement rule.

We run a facilitator in production. When the paper landed, we had two choices: skim the abstract and move on, or take it seriously and audit our own code against every attack class they described. We chose the latter.

Here's what we found, what we fixed, and a practical audit checklist for anyone operating an x402 payment gateway.

The Paper: A Quick Summary

The EPFL/Zhejiang team (arXiv:2607.19545) built an automated testing framework that systematically probes x402 payment gateways for violations of the protocol's three core guarantees:

  1. Payment verification — the facilitator must cryptographically verify that payment was made before delivering the service
  2. Settlement finality — once verified, the settlement must either succeed atomically or fail without delivering the service
  3. Resource protection — the facilitator must not allow attackers to consume paid resources without paying (gas abuse, replay, double-spend)

They classified attacks into four families:

Attack ClassWhat It ExploitsImpact
Free ShoppingSettle failure → still serve. Invalid signatures accepted. Zero-amount payments pass.Attacker gets paid service for free
Asset TheftFacilitator wallet compromise. Refund-to-attacker. Settlement amount manipulation.Attacker drains facilitator funds
Service DenialReplay attacks. Sig reuse. Malicious payloads causing facilitator crash.Legitimate agents can't pay or get service
Gas AbuseFacilitator pays gas for malicious txns. Spam causing repeated on-chain ops.Facilitator bleeds gas fees

The paper confirmed that Coinbase, PayAI, and Mogami acknowledged and fixed 6 vulnerabilities in February 2026. But the broader finding — every facilitator had at least one vulnerability — is the real headline.

Our Audit: Methodology

We run a production x402 facilitator handling payment for 326 services. The codebase spans four files that matter for payment security:

Our audit mapped each attack class from the paper to specific code paths, then traced every path manually to verify the control flow.

Free Shopping: The Most Critical Check

This is the big one. Free Shopping means "attacker gets paid service without paying." The paper found it in the majority of facilitators. The root cause is almost always the same pattern: settle failure after verify success, but the service is still delivered.

Here's the correct control flow for a paid request:

1. Parse payment from HTTP header
2. Call facilitator.verify(signature, amount, network)
3. If !verify.isValid → return 402 (don't serve)
4. Call facilitator.settle(verifiedPayment)
5. If !settle.success → return 402 (don't serve)  ← THIS IS THE CRITICAL CHECK
6. Generate receipt
7. Forward request to service
8. Return service response + receipt

Step 5 is where most facilitators fail. They verify successfully (step 3), then if settlement fails (step 5), they either: (a) serve the content anyway — "the payment was verified, settlement will probably go through" (b) log an error and continue — "we'll reconcile later" (c) return a partial response — "here's a degraded version"

All three are Free Shopping vulnerabilities.

Our main proxy path (proxy.js → x402.js) passed this check: the processPayment() function properly returns null on settlement failure, and the caller returns 402 without forwarding the request. The primary payment path is secure.

What We Found: One Real Vulnerability

⚠️ Vulnerability Found — x402.js processPayment() function: when settlement failed, two code paths (gas and api-review endpoints) still delivered the service response instead of returning 402. The settlement call returned an error, but the function continued execution and returned the paid service data.

Here's what the vulnerable code pattern looked like (simplified):

// VULNERABLE PATTERN (simplified)
async function processPayment(payload, priceCents, networkId) {
  // Step 1: Verify signature — this works correctly
  const verifyResult = await facilitatorVerify(payload, priceCents, networkId);
  if (!verifyResult || !verifyResult.isValid) {
    return null; // ✅ Correct: no verify → no service
  }

  // Step 2: Settle — but settlement failure was NOT handled
  const settleResult = await facilitatorSettle(verifyResult);
  // ❌ BUG: settleResult could be null or failed, but code continues

  // Step 3: Return paid service data
  return {
    receipt: generateReceipt(verifyResult),
    data: await fetchServiceData(verifyResult.serviceEndpoint)
  };
  // ❌ Service delivered even when settlement failed
}

The fix was straightforward: check the settlement result and bail out if it failed:

// FIXED
async function processPayment(payload, priceCents, networkId) {
  const verifyResult = await facilitatorVerify(payload, priceCents, networkId);
  if (!verifyResult || !verifyResult.isValid) {
    return null;
  }

  const settleResult = await facilitatorSettle(verifyResult);
  if (!settleResult || !settleResult.success) {
    console.error('[x402] SETTLE FAILED — returning 402, no service delivered');
    return null; // ✅ Fixed: settle failure → no service
  }

  return {
    receipt: generateReceipt(settleResult),
    data: await fetchServiceData(verifyResult.serviceEndpoint)
  };
}

This was a real bug. In the narrow window between verify and settle, if the facilitator returned a settlement error (network blip, facilitator-side issue, gas spike), the service would still be delivered. The attacker would get a paid API call for free.

We deployed the fix with zero-downtime reload, verified all four affected endpoints returned correct 402 responses, and the backup files are timestamped and stored.

Audit Results: Attack-by-Attack

Here's how our facilitator scored against every attack class in the paper:

Attack ClassStatusDetails
Free Shopping — settle failure🔴 Found & FixedFixed in processPayment(); settle failure now returns null → 402
Free Shopping — invalid sig🟢 SafefacilitatorVerify() properly validates all signatures before returning isValid
Free Shopping — zero amount🟢 SafeMinimum 1 cent enforced; schema.exact validation catches zero amounts
Asset Theft — wallet keys🟢 SafePlatform wallet is env-var only; no private key in code or logs
Asset Theft — refund redirect🟡 Low RiskRefunds go to payment source address (on-chain tx); facilitator wallet not used for refunds
Service Denial — sig replay🟢 SafesigUsed() / lockSig() dedup; each signature usable exactly once
Service Denial — tx replay🟢 SafetxUsed() / lockTx() dedup per transaction hash
Gas Abuse — spam txns🟡 Mitigated5-min pending tx timeout; invalid txns cleaned without on-chain cost
Gas Abuse — malicious payload🟢 SafeAmount validated client-side before any on-chain operation

What Every x402 Operator Should Check

Based on this audit, here's a practical checklist for anyone running an x402 payment gateway:

1. Trace your settle failure path

This is the #1 vulnerability. Find every code path that calls settle, and verify that settle failure means no service delivery, no exceptions. Don't trust error handlers that "log and continue." Don't trust try/catch blocks that don't re-throw. The only acceptable behavior on settle failure is returning 402.

2. Signature deduplication is not optional

If your facilitator doesn't track used signatures (or nonces) and reject replays, an attacker can pay once and call the same paid endpoint infinitely. This is trivial to implement (a Set or Map of used sigs with TTL expiry) but catastrophic to miss.

3. Zero-amount transactions must be rejected

The x402 challenge format includes maxAmountRequired. Verify that your settlement code rejects zero-amount payments even if the facilitator says they're valid. A facilitator bug that accepts zero-amount settlements becomes a Free Shopping vulnerability downstream.

4. Receipts are not optional — they're accountability

The paper notes that facilitators without receipt generation can't provide dispute resolution. If an agent claims they paid but didn't get service, the facilitator has no evidence to resolve the dispute. Cryptographically signed receipts (linking payment txHash → service endpoint → response hash) are the foundation of accountability in agent payments.

5. Test your 402 responses in production

Set up a monitor that calls your endpoints with invalid signatures and verifies you get a proper 402 response (not a 200 with trial data, not a 500, not a timeout). The EPFL team built automated testers for this — you should too.

Why This Matters Beyond Security

The EPFL paper is a milestone for the x402 ecosystem. It's the first independent, academic security audit of the protocol in production — and it shows that the protocol design is sound (the attack surface is implementation errors, not protocol flaws).

But there's a bigger story here: security audits create trust, and trust is what's missing from agent-to-agent payments.

Right now, the biggest barrier to M2M payment adoption isn't technology. The payment rails work — Cloudflare, Coinbase, Stripe, and 40+ x402 Foundation members have proven that. The barrier is that agents (and their developers) don't trust the payment infrastructure. They don't know if their money is safe. They don't know if they'll get what they paid for. They don't know if there's recourse when something goes wrong.

Independent security audits — and operators who publicly share their results — are part of building that trust. Every facilitator that passes an audit and publishes the results makes the whole ecosystem stronger.

We're doing our part. If you run an x402 facilitator, we encourage you to do the same.

References

Disclosure: We found and fixed the vulnerability described in this post on August 9, 2026, the same day the EPFL paper came to our attention. No user funds were at risk — the vulnerability was in the service-delivery path, not the fund-custody path. The affected endpoints (gas, api-review) had low paid transaction volume. We're publishing these results to help the x402 ecosystem mature.