Skip to content

Payment replay is not explicitly prevented across identical requests #803

@yeastybunks

Description

@yeastybunks

Overview

The x402 protocol validates payments per request, but there is currently no explicit safeguard to prevent the same valid payment from being replayed across multiple identical requests. This can lead to unintended repeated access to paid endpoints using a single payment.

Problem Description

If a client captures a valid payment payload (headers/signature) and reuses it for the same endpoint with identical parameters, the middleware may accept the request again if no replay protection is enforced. This is especially problematic for paid APIs that assume one payment equals one successful request.

Expected Behavior

  • A payment should be accepted at most once for a given request context.
  • Replayed payments should be rejected with a clear error.
  • Replay protection behavior should be well-defined and documented.

Steps to Reproduce

  1. Send a valid paid request to an x402-protected endpoint.
  2. Capture the payment headers/signature.
  3. Replay the same request with identical headers.
  4. Observe that the request may be accepted again.

Example code

```ts
// First request (valid payment)
fetch("/api/paid", {
  headers: {
    "X-402-Payment": "<signed-payload>",
  },
});

// Second request (replay of the same payment)
fetch("/api/paid", {
  headers: {
    "X-402-Payment": "<signed-payload>",
  },
});

Proposed Solution

  • Introduce replay protection by associating each payment with a unique identifier (e.g., nonce, request hash, or payment ID).
  • Track consumed payment identifiers for a configurable time window.
  • Reject requests that attempt to reuse an already-consumed payment.
  • Clearly document replay protection guarantees and limitations.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions