---
title: "x402 security checklist for servers and agents | Settlens"
description: "A printable x402 security checklist for resource servers, facilitators and AI agent clients, with the Settlens check that tests each control where one exists."
url: https://settlens.com/learn/x402-security-checklist
last_updated: 2026-10-13
published: 2026-10-13
---

# x402 security checklist

> **In short:** A checklist of x402 security controls for resource servers, facilitators and agent clients, grounded in the V2 specifications. Each control names the Settlens check that tests it and the mode it needs (passive, offline, active or facilitator), or says plainly that it needs manual review.

Concrete controls for the three parties of an x402 payment, grounded in the V2 specifications. Each control lists the Settlens check that tests it, or says plainly when no automated check exists.

This checklist turns the [x402 V2 core](https://github.com/x402-foundation/x402/blob/main/specs/x402-specification-v2.md), [HTTP transport](https://github.com/x402-foundation/x402/blob/main/specs/transports-v2/http.md) and [exact scheme](https://github.com/x402-foundation/x402/blob/main/specs/schemes/exact/scheme_exact.md) specifications into 43 controls: 18 for resource servers, 14 for facilitators and 11 for agent clients. 32 of them map to at least one automated Settlens check. For the others, the coverage line says what helps, or that the control needs your own review.

Use the identifiers (RS-01, FA-01, AG-01) to track findings. The page is printable: navigation, footer and the table of contents are hidden in the print view.

> **How to read the coverage line**
>
> Under each control, a check id names the Settlens check that tests it, followed by the mode the check needs; see [check modes](https://settlens.com/learn/x402-security-checklist#check-modes) below. Full definitions, severities and remediation are in the [check reference](https://settlens.com/docs/checks).

## Resource servers

The service that sells the resource. Most of these controls are visible from outside, so a passive scan tests them without paying.

_Resource servers: x402 security controls_

| ID | Control and coverage |
| --- | --- |
| RS-01 | Answer HTTP 402 to every request that carries no valid payment, before any business logic runs.; **Settlens:** `transport.status_402` (passive) |
| RS-02 | Send the terms in the [`PAYMENT-REQUIRED`](https://settlens.com/learn/glossary#payment-required) header as Base64-encoded JSON. Do not rely on the response body.; **Settlens:** `transport.payment_required_header` (passive), `transport.payment_required_encoding` (offline) |
| RS-03 | Emit a V2 object (`x402Version` 2, a `resource` object, a non-empty `accepts` array) that the official `@x402/core` schema accepts.; **Settlens:** `schema.payment_required` (offline), `schema.official_x402_sdk` (offline) |
| RS-04 | Set `resource.url` to the exact URL the client requested, including path and query.; **Settlens:** `binding.resource_url` (offline) |
| RS-05 | Make every `accepts` entry complete: scheme, [CAIP-2](https://settlens.com/learn/glossary#caip-2) network, positive integer amount in [atomic units](https://settlens.com/learn/glossary#atomic-units), asset, `payTo` (a 20-byte address on `eip155` networks) and a positive `maxTimeoutSeconds`.; **Settlens:** `schema.payment_requirements` (offline) |
| RS-06 | For EIP-3009 tokens, publish the token's real EIP-712 name and version in `extra.name` and `extra.version`.; **Coverage:** Not scanned. verify-payment uses them to rebuild the EIP-712 domain. |
| RS-07 | Advertise each payment option once.; **Settlens:** `schema.duplicate_requirements` (offline) |
| RS-08 | Keep `maxTimeoutSeconds` as short as settlement allows.; **Settlens:** `freshness.timeout_window` (offline) |
| RS-09 | Serve paid resources over HTTPS only.; **Settlens:** `transport.https` (passive) |
| RS-10 | Serve the paid resource at its canonical URL, without redirects.; **Settlens:** `transport.redirect` (passive) |
| RS-11 | Keep the 402 response small and never put protected content in it.; **Settlens:** `transport.response_body_limit` (passive). Size only: a scan cannot tell whether the body holds protected content. |
| RS-12 | Return the same terms for identical requests, or bind any dynamic pricing to the request on purpose.; **Settlens:** `stability.payment_requirements` (passive) |
| RS-13 | [Fail closed](https://settlens.com/learn/glossary#fail-closed): run the handler only after the payment is verified (or settled, under the `upfront` and `escrow` flows), never on a missing, malformed or invalid signature.; **Settlens:** `security.invalid_signature_fail_closed` (active) |
| RS-14 | Answer 400 to a malformed payment and 402 to a payment that fails verification or settlement.; **Settlens:** `transport.invalid_payment_status` (active) |
| RS-15 | Match the client's `accepted` object against your own `accepts` entries, and send your own requirement to `/verify` and `/settle`.; **Coverage:** No automated check: review manually. |
| RS-16 | Reject transfer methods and payment flows you do not support (`extra.assetTransferMethod`, `extra.paymentFlow`).; **Coverage:** No automated check: review manually. |
| RS-17 | When settlement fails, do not deliver: answer 402 with a `PAYMENT-RESPONSE` whose `success` is false. Treat [`settlement_pending`](https://settlens.com/learn/x402-error-codes#settlement-pending) as unresolved and reconcile on chain before retrying.; **Coverage:** Not covered: Settlens never calls /settle. |
| RS-18 | Re-test after every deploy and on a schedule, so a regression is caught before agents pay into it.; **Coverage:** settlens monitor and the GitHub Action re-run the passive checks. |

## Facilitators

The service that verifies and settles payments. Its capability endpoint can be scanned passively; its `/verify` behavior is tested only during an authorized [active probe](https://settlens.com/learn/glossary#active-probe). The [facilitator security guide](https://settlens.com/learn/x402-facilitator-security) explains the risks behind these controls.

_Facilitators: x402 security controls_

| ID | Control and coverage |
| --- | --- |
| FA-01 | Serve `GET /supported` with HTTP 200 and a JSON content type.; **Settlens:** `facilitator.reachable` (facilitator), `facilitator.supported_status` (facilitator), `facilitator.content_type` (facilitator) |
| FA-02 | Return the standard `SupportedResponse`: `kinds`, `extensions` and `signers`.; **Settlens:** `facilitator.supported_schema` (facilitator) |
| FA-03 | List at least one `x402Version` 2 kind.; **Settlens:** `facilitator.v2_capability` (facilitator) |
| FA-04 | List each version, scheme and network combination once.; **Settlens:** `facilitator.duplicate_kinds` (facilitator) |
| FA-05 | Publish signer addresses for every network you settle on, or for its CAIP-2 namespace wildcard such as `eip155:*`.; **Settlens:** `facilitator.signer_coverage` (facilitator) |
| FA-06 | Support every scheme and network that the resource servers you serve advertise.; **Settlens:** `facilitator.requirement_coverage` (facilitator) |
| FA-07 | Serve the facilitator API over HTTPS only.; **Settlens:** `facilitator.https` (facilitator) |
| FA-08 | Keep `/supported` small.; **Settlens:** `facilitator.response_body_limit` (facilitator) |
| FA-09 | Answer `/verify` with a standard `VerifyResponse` carrying a boolean `isValid`.; **Settlens:** `facilitator.verify_reachable` (active), `facilitator.verify_response_schema` (active) |
| FA-10 | Verify the signature cryptographically before answering `isValid: true`. A forged or all-zero signature must be rejected.; **Settlens:** `security.facilitator_rejects_invalid_signature` (active) |
| FA-11 | Keep `/verify` read-only: it must not commit payment state or write on chain.; **Coverage:** No automated check: review manually. |
| FA-12 | For EIP-3009, check that the signer is `authorization.from` and never the zero address, the balance, the exact amount, the validity window, the token and the network, then simulate `transferWithAuthorization`.; **Coverage:** verify-payment checks signer, recipient, amount and window offline; balance and simulation need the chain. |
| FA-13 | Make settlement produce exactly one transfer of `amount` of `asset` to `payTo`, and return a failure, never a success, when the authorization's nonce is already used.; **Coverage:** Not covered: Settlens never calls /settle. |
| FA-14 | Return `settlement_pending` with the broadcast transaction hash when confirmation cannot be established.; **Coverage:** Not covered: Settlens never calls /settle. |

## Agent clients

The software that pays, often an AI agent with a wallet. These controls decide whether to sign at all. The policy checks run offline in the [Settlens MCP server](https://settlens.com/mcp), so an agent can apply them to every 402 before paying. How to write the policy is covered in the [agent spending policy guide](https://settlens.com/learn/agent-spending-policy).

_Agent clients: x402 security controls_

| ID | Control and coverage |
| --- | --- |
| AG-01 | Read the terms from `PAYMENT-REQUIRED` and validate them before signing: Base64 JSON, V2 shape, the official schema and well-formed options.; **Settlens:** `transport.payment_required_encoding` (offline), `schema.official_x402_sdk` (offline), `schema.payment_required` (offline), `schema.payment_requirements` (offline) |
| AG-02 | Check that `resource.url` equals the URL you requested.; **Settlens:** `binding.resource_url` (offline) |
| AG-03 | Pay only over HTTPS.; **Settlens:** `transport.https` (passive) |
| AG-04 | Allowlist recipients (`payTo`).; **Settlens:** `policy.recipient` (offline) |
| AG-05 | Allowlist assets: token contract addresses or mints.; **Settlens:** `policy.asset` (offline) |
| AG-06 | Cap the amount in atomic units and pair the cap with an asset allowlist: a ceiling means nothing without the asset, because tokens have different decimals.; **Settlens:** `policy.maximum_amount` (offline) |
| AG-07 | Restrict networks and schemes to the ones you can verify.; **Settlens:** `policy.network` (offline), `policy.scheme` (offline) |
| AG-08 | Pay only with an option that satisfies every constraint at once; when none does, do not pay.; **Settlens:** `policy.acceptable_option` (offline) |
| AG-09 | Skip options whose `paymentFlow` you do not recognize, and prefer `authorization` when a resource also offers `upfront` or `escrow`.; **Coverage:** No automated check: review manually. |
| AG-10 | Sign exactly the advertised amount to the advertised `payTo`, with a short `validBefore` and a random 32-byte [nonce](https://settlens.com/learn/glossary#nonce).; **Coverage:** verify-payment checks the signed authorization offline. |
| AG-11 | Treat terms that change between identical requests as a reason to stop and review.; **Settlens:** `stability.payment_requirements` (passive) |

## Check modes

Each Settlens check runs in one mode. The descriptions below come from the check catalog.

_Settlens check modes_

| Mode | What it needs |
| --- | --- |
| passive | Needs a live, unauthenticated request to the paid resource (settlens scan, settlens monitor, MCP scan_endpoint). Never sends a payment. |
| offline | Evaluated from the PaymentRequired content alone: runs offline in the MCP tool evaluate_payment_requirements and in every passive scan (policy.acceptable_option only in the agent tools). |
| active | Runs only with --active --authorized --authorization-ref: one intentionally invalid PAYMENT-SIGNATURE is sent. /settle is never called and no wallet or key is used. |
| facilitator | Reads a facilitator's GET /supported capabilities (settlens facilitator, scan --facilitator, MCP scan_facilitator). |

> **Active checks need written authorization**
>
> Checks in the active mode run only with `--active --authorized --authorization-ref` and the endpoint owner's approval. They send one intentionally invalid `PAYMENT-SIGNATURE`, never call `/settle`, never move funds and need no wallet or private key.

## What this checklist does not cover

It covers the x402 exchange itself. It does not replace an application security review, smart contract audits of the tokens you accept, key management for the wallets that sign or settle, or legal and regulatory advice. A Settlens report is evidence of observed behavior, not a certification.

To understand the protocol behind each control, read [What is x402?](https://settlens.com/learn/what-is-x402), the [V2 headers reference](https://settlens.com/learn/x402-v2-headers) and the [EIP-3009 guide](https://settlens.com/learn/eip-3009), with terms defined in the [glossary](https://settlens.com/learn/glossary). To see these controls fail in practice, read [x402 security failure modes](https://settlens.com/blog/x402-security-failure-modes). For signature-level details of the EVM flow, see the [exact EVM scheme specification](https://github.com/x402-foundation/x402/blob/main/specs/schemes/exact/scheme_exact_evm.md).

## Sources

1. [x402 protocol specification, version 2](https://github.com/x402-foundation/x402/blob/main/specs/x402-specification-v2.md) — x402 Foundation
2. [x402 HTTP transport, version 2](https://github.com/x402-foundation/x402/blob/main/specs/transports-v2/http.md) — x402 Foundation
3. [x402 scheme: exact](https://github.com/x402-foundation/x402/blob/main/specs/schemes/exact/scheme_exact.md) — x402 Foundation
4. [x402 scheme: exact on EVM](https://github.com/x402-foundation/x402/blob/main/specs/schemes/exact/scheme_exact_evm.md) — x402 Foundation
