Skip to content

About

A Rust CLI that black-box audits an x402-protected HTTP endpoint for protocol conformance and common payment-gating/security mistakes, producing a deterministic, CI-friendly report.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

Repository files navigation

x402-audit

Black-box conformance and security auditing for x402 HTTP endpoints.

x402-audit is a Rust CLI that tests whether an HTTP endpoint actually behaves correctly as an x402 payment-protected resource.

It validates the wire protocol, payment requirements, discovery metadata, rejection behavior, and basic payment-gating invariants — without requiring you to modify the application being tested, and without ever spending money.

cargo install x402-audit
x402-audit https://api.example.com/paid/weather
x402-audit
https://api.example.com/paid/weather 0.1.0

HTTP
  ✓  endpoint reachable
  ✓  returns 402 Payment Required without payment
  ✓  PAYMENT-REQUIRED header present
  ✓  PAYMENT-REQUIRED header decodes as base64
  ...

Protocol
  ✓  x402Version = 2 (v2)
  ✓  network `eip155:84532` is a valid CAIP-2 identifier
  ✓  payTo is a valid EVM address
  ✗  amount `not-a-number` is not a valid non-negative decimal (atomic units)
      [REQ_AMOUNT_VALID]

Discovery
  ✓  bazaar extension present
  ✗  bazaar extension must be an object with `info` (object) and `schema` (object)
      [BAZAAR_SHAPE_VALID]

Payment gate
  ✓  endpoint rejected a payment payload whose accepted.amount does not match (HTTP 400)
  ✗  endpoint returned 200 OK and released the protected resource for a malformed PAYMENT-SIGNATURE
      [PAYMENT_MALFORMED_B64_REJECTED]

Result: FAIL
3 errors, 1 warning

Why?

An endpoint can appear to support x402 while still having subtle implementation problems:

  • malformed 402 Payment Required responses
  • invalid or incomplete payment requirements
  • incorrect network or asset identifiers
  • inconsistent resource metadata
  • malformed Bazaar extensions (extensions.bazaar.bazaar, missing input.method, …)
  • missing HTTP headers
  • accepting malformed payment payloads
  • failing to reject invalid payment proofs
  • payment-gating behavior that does not match the advertised requirements

These problems are particularly difficult to diagnose because the failure may occur across several layers:

HTTP
  ↓
x402 wire format
  ↓
payment requirements
  ↓
payment authorization
  ↓
facilitator verification
  ↓
settlement
  ↓
resource delivery

x402-audit turns those layers into an automated test suite. Existing validators answer "does this JSON look correct?"; x402-audit additionally answers "does this HTTP endpoint behave like a correct x402 resource?" by exercising the payment gate with safely-invalid payloads.

Install

Requires Rust 1.75+ (no system dependencies — HTTP is built on rustls).

cargo install x402-audit
# or build from source
cargo build --release

Usage

x402-audit URL                      # human-readable report
x402-audit URL --json               # machine-readable (CI)
x402-audit URL --github-summary     # GitHub Actions job summary
x402-audit URL --strict             # warnings count as failures
x402-audit URL --exit-code          # exit 0/1/2 (see below)
x402-audit URL --method POST --body '{"q":"weather"}' -H "X-Key: secret"

x402-audit --discover https://api.example.com          # audit every listed resource
x402-audit --discover --limit 50 URL                   # cap the number of resources
x402-audit --discover --json URL > x402-discover.json  # aggregated JSON (CI)
Flag Meaning
--json Stable, machine-readable JSON report on stdout
--github-summary Markdown job-summary for GitHub Actions
--strict Treat warnings as failures
--exit-code Exit 0 = PASS, 1 = FAIL, 2 = UNREACHABLE
--quiet Only failures and the summary
--discover Treat the URL as a discovery origin or .well-known/x402 manifest and audit every listed resource
--limit N Max resources audited per discovery run (default 25, 0 = unlimited)
-H/--header, --body, --method, --timeout Request configuration

Discovery mode

--discover fetches the machine-readable manifest at /.well-known/x402 (falling back to /.well-known/x402.json) and audits every listed resource in one run — ideal for CI gates over an entire API surface. The parser is shape-tolerant: it accepts the manifest formats observed in production (resources as URL strings or objects, endpoints with relative paths, resource-groups), resolves relative paths against the manifest origin, deduplicates, and respects --limit. A manifest that cannot be fetched or parsed is an UNREACHABLE result (exit 2); any failing resource makes the whole run FAIL (exit 1).

JSON output

Every finding has a stable identifier, severity, status, and message — perfect for GitHub Actions later:

{
  "tool": "x402-audit",
  "target": "https://api.example.com/paid/weather",
  "result": "FAIL",
  "summary": { "passed": 40, "failed": 3, "warnings": 1, "skipped": 0 },
  "findings": [
    {
      "id": "PAYMENT_MALFORMED_B64_REJECTED",
      "group": "payment_gate",
      "severity": "error",
      "status": "fail",
      "message": "endpoint returned 200 OK and released the protected resource for a malformed (non-base64) PAYMENT-SIGNATURE header"
    }
  ]
}

In CI

x402-audit https://api.example.com/paid/weather \
  --json --exit-code > x402-report.json

See .github/workflows/ci.yml for a complete workflow, including publishing the report as an artifact.

Try it locally (no network, no wallet)

The crate ships a bundled fixture server with a correct implementation and several intentionally broken ones:

# Terminal 1 — start a broken endpoint (or `manifest` for discovery mode)
cargo run --example fixture-server --features fixtures manifest

# Terminal 2 — audit it (discovery mode audits every endpoint at once)
cargo run -- x402-audit --discover http://127.0.0.1:PORT
# or, for a single endpoint:
cargo run -- x402-audit http://127.0.0.1:PORT/weather

Fixture kinds: correct, v1, broken-protocol, broken-bazaar, broken-requirements, leaky-gate, no-gate, manifest.

cargo test --all-features   # proves the auditor catches each broken fixture
Fixture The auditor reports
correct PASS (48 checks)
v1 warning + v2 checks skipped (graceful degradation)
broken-protocol RESOURCE_URL_VALID, REQ_ACCEPTS_REQUIRED_FIELDS
broken-bazaar BAZAAR_SHAPE_VALID (nested-key bug)
broken-requirements REQ_NETWORK_EIP155, REQ_ASSET_VALID, REQ_PAYTO_VALID, REQ_AMOUNT_VALID
leaky-gate all 10 payment-gate checks (PAYMENT_*_REJECTED)
no-gate HTTP_402_RETURNED, HTTP_HEADER_PRESENT
manifest one server, three endpoints + a .well-known/x402 manifest; --discover finds them all

Validated against production

Live audits of real public x402 endpoints (no payments made — the payment-gate tests only send structurally-invalid payloads):

Endpoint Result Findings
kaisha-api.hp-vladic.workers.dev/resolve (Base + Solana) PASS 44 checks, 0 errors
langston.click/api/search (Solana, USDC) FAIL BAZAAR_METHOD_PRESENT — bazaar.info.input.method missing, facilitators can't call it
api.octodamus.com/v2/agent-signal (Base, USDC) FAIL RESOURCE_URL_VALID — resource is null; v2 requires a ResourceInfo object
agent402.tools/api/dns (13 accepts, 12 networks) FAIL REQ_NETWORK_CAIP2 — algorand:…kit8= is the full base64 Algorand MainNet genesis hash; the reference must be its first 32 base64url chars (registry-resolved hint)

All four endpoints correctly rejected every invalid payment payload (no leaky gates found). This run also surfaced a real validator bug — CAIP-2 references may contain _, which x402-audit now accepts (see parse_caip2).

Networks are now resolved against a bundled ChainAgnostic registry snapshot (data/networks.json), so audits name chains (eip155:8453 → Base) and recognize malformed references like untruncated genesis hashes — see docs/checks.md for provenance and refresh instructions.

--discover audits whole manifests in one run and finds what single-URL audits can't: the kaisha manifest surfaced /catalog (listed, but not payment-gated: HTTP_402_RETURNED, HTTP_HEADER_PRESENT), and two of agent402's advertised URLs (/api/extract, /api/render) turned out to be dead 404s.

Checks

The audit runs four groups of checks:

  1. HTTP — reachability, 402 semantics, PAYMENT-REQUIRED header, base64/JSON decoding, content type.
  2. Protocol — x402 v2 PaymentRequired envelope: version, resource metadata, and every accepts[] entry (scheme, CAIP-2 network, asset, payTo, amount, maxTimeoutSeconds, extra), plus header/body consistency.
  3. Discovery — the bazaar extension: shape, input schema, method metadata, advertised JSON-Schema sanity, routeTemplate.
  4. Payment gate — ten safely-invalid PAYMENT-SIGNATURE payloads that a conformant endpoint must reject (the protected resource must never be returned).

The complete registry with stable IDs lives in docs/checks.md.

Documentation

Design principles

Black-box first

The tool tests the endpoint through HTTP rather than requiring framework-specific integration.

Deterministic

The same endpoint and test configuration produce the same result. Reports contain no timestamps; checks and negative tests run in a fixed order.

Safe by default

The default audit suite never spends real money and never attempts destructive operations. The payment-gate tests only send structurally-invalid payloads that cannot be settled.

Protocol-oriented

Tests correspond to documented x402 behavior and explicit security invariants, not arbitrary style opinions. Several checks were derived from real ecosystem integration failures (see docs/methodology.md).

CI-friendly

Every finding has a stable identifier, severity, description, and machine-readable representation.

What this is not

x402-audit is not:

  • an x402 SDK
  • a facilitator
  • a payment processor
  • a wallet
  • an x402 gateway
  • a discovery marketplace
  • a blockchain explorer

It is a testing and auditing tool for existing x402 implementations.

Limitations (v0.1)

  • Audits x402 v2 with the exact scheme and EVM network semantics (Base/Ethereum). Other networks and schemes are reported but not fully audited.
  • Network resolution uses a bundled ChainAgnostic registry snapshot (data/networks.json): known networks are named, unknown ones warn (fail under --strict). See docs/checks.md for refresh steps.
  • Does not positively verify that a valid payment is accepted — that would require a wallet and real (or testnet) funds. The positive path is out of scope by design.
  • Does not audit facilitator /verify / /settle endpoints.

License

MIT — see LICENSE.

About

A Rust CLI that black-box audits an x402-protected HTTP endpoint for protocol conformance and common payment-gating/security mistakes, producing a deterministic, CI-friendly report.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages