Security middleware for x402 agentic payments — PII redaction, spending policy, and replay detection before blockchain commit
presidio-hardened-x402 is an early-stage Python project in the AI payments / x402 ecosystem, focused on agentic-payments, hardening, pii-detection, privacy. It currently has 13 GitHub stars and 0 forks, and sits alongside related tools like routeweiler-python-sdk, Agent-Layer, SubEtha, inflow-node, inflow-cli, sample-agentic-serverless-payments.
v0.9.1 — security patch: dependency-audit floors for
click/setuptools, missing-payment-header log exposure hardening, andsetup-uvv8.3.2 CI action pin.
Security middleware for the x402 payment protocol.
Intercepts x402 payment requests before transmission to servers and facilitators to enforce:
pay_to and currency (v0.4.0)remote_screening=True mode offloads PII analysis to the hosted screen.presidio-group.eu service via ScreeningClient; avoids the in-process spaCy dependency (v0.4.0)pay_to allowlist blocks payments to attacker-controlled addresses when a DNS-poisoned 402 response substitutes the recipient (chain-06 mitigation) (v0.4.0)ScreeningPipeline) is payment-protocol-independent; everything x402-specific lives in bindings/x402. Embed on a different rail by implementing PaymentProtocolBinding — the security guarantees travel with the core (v0.5.0)python -m presidio_x402.conformance, 7 end-to-end checks, no network), and integration quickstarts for Coinbase CDP, LangChain, and CrewAI (v0.5.0)Part of the presidio-hardened-* toolkit family.
pip install presidio-hardened-x402
For full NLP-based PII detection (PERSON, ORG, location, etc.):
pip install "presidio-hardened-x402[nlp]"
python -m spacy download en_core_web_sm
For production replay guard with cross-process deduplication:
pip install "presidio-hardened-x402[redis]"
For Prometheus metrics export:
pip install "presidio-hardened-x402[prometheus]"
For policy-as-code schema validation:
pip install "presidio-hardened-x402[schema]"
import httpx
async def pay_and_fetch(url: str, signer) -> httpx.Response:
async with httpx.AsyncClient() as client:
resp = await client.get(url)
if resp.status_code == 402:
payment_details = parse_402_header(resp.headers)
# No PII check. No policy check. No replay check.
payment_token = await signer.sign(payment_details)
resp = await client.get(url, headers={"X-PAYMENT": payment_token})
return resp
from presidio_x402 import HardenedX402Client
async def my_signer(details):
# Your existing signing logic (eth-account, solders, CDP SDK, etc.)
...
client = HardenedX402Client(
payment_signer=my_signer,
policy={
"max_per_call_usd": 0.10,
"daily_limit_usd": 5.0,
"per_endpoint": {"https://api.example.com": 1.0},
},
pii_action="redact", # redact | block | warn
pii_entities=["EMAIL_ADDRESS", "PERSON", "US_SSN", "CREDIT_CARD"],
replay_ttl=300, # seconds
)
response = await client.get("https://api.example.com/resource")
What happens transparently:
GET /resource → server returns 402 with payment detailsfrom presidio_x402 import HardenedX402Client, PolicyConfig
policy = PolicyConfig(
max_per_call_usd=0.05, # block if maxAmountRequired > this
daily_limit_usd=2.00, # block if 24h aggregate spend would exceed this
per_endpoint={
"https://premium-api.io": 0.50, # per-endpoint daily limit
},
window_seconds=86400, # time window for aggregate limits (default: 24h)
agent_id="my-agent-v1", # tag audit events with an agent identifier
)
client = HardenedX402Client(payment_signer=signer, policy=policy)
# regex mode (default, zero-setup): catches structured PII
client = HardenedX402Client(
payment_signer=signer,
pii_mode="regex",
pii_entities=["EMAIL_ADDRESS", "PHONE_NUMBER", "US_SSN", "CREDIT_CARD"],
pii_action="redact",
)
# nlp mode: full spaCy NER (requires: pip install presidio-hardened-x402[nlp])
client = HardenedX402Client(
payment_signer=signer,
pii_mode="nlp",
pii_entities=["EMAIL_ADDRESS", "PERSON", "LOCATION", "US_SSN"],
pii_action="block", # raise PIIBlockedError instead of redacting
)
# In-memory (default, single-process)
client = HardenedX402Client(payment_signer=signer, replay_ttl=300)
# Redis-backed (production, cross-process)
client = HardenedX402Client(
payment_signer=signer,
replay_ttl=300,
redis_url="redis://localhost:6379/0",
)
import sys
from presidio_x402 import HardenedX402Client
from presidio_x402.audit_log import StreamAuditWriter
client = HardenedX402Client(
payment_signer=signer,
audit_writer=StreamAuditWriter(sys.stdout), # write JSON-L to stdout
)
For high-value payments that require human or system oversight before execution:
from presidio_x402 import HardenedX402Client
from presidio_x402.mpa import MPAConfig, MPAApproverConfig, MPAEngine
mpa = MPAEngine(MPAConfig(
threshold=2, # require 2 of 3 approvals
min_amount_usd=1.00, # only for payments ≥ $1.00
timeout_seconds=30,
approvers=[
MPAApproverConfig("alice", mode="webhook",
webhook_url="https://approvals.internal/alice"),
MPAApproverConfig("bob", mode="webhook",
webhook_url="https://approvals.internal/bob"),
MPAApproverConfig("charlie", mode="webhook",
webhook_url="https://approvals.internal/charlie"),
],
))
client = HardenedX402Client(payment_signer=signer, mpa_engine=mpa)
Approval endpoints receive a POST with payment details and must return {"approved": true}.
For machine-to-machine approvals, use mode="crypto" with HMAC-SHA256 countersignatures
and pass them via mpa_signatures={"approver_id": "hex_sig", ...} in the request kwargs.
from presidio_x402 import HardenedX402Client
from presidio_x402.metrics import MetricsCollector
collector = MetricsCollector()
client = HardenedX402Client(payment_signer=signer, metrics_collector=collector)
# Expose /metrics endpoint (e.g., FastAPI)
from prometheus_client import generate_latest, CONTENT_TYPE_LATEST
@app.get("/metrics")
def metrics():
return Response(generate_latest(), media_type=CONTENT_TYPE_LATEST)
Available metrics: x402_payments_total, x402_payment_amount_usd (histogram),
x402_pii_detections_total, x402_policy_violations_total,
x402_replay_detections_total, x402_mpa_events_total.
Define spending policy in a TOML or JSON file and validate it against the x402 policy JSON Schema:
# policy.toml
max_per_call_usd = 0.10
daily_limit_usd = 5.00
agent_id = "my-agent"
[per_endpoint]
"https://premium-api.io" = 0.50
[mpa]
threshold = 2
min_amount_usd = 1.00
timeout_seconds = 30
[[mpa.approvers]]
approver_id = "alice"
mode = "webhook"
webhook_url = "https://approvals.internal/alice"
from presidio_x402.x402_policy_schema import load_policy_file
policy = load_policy_file("policy.toml")
client = HardenedX402Client(payment_signer=signer, policy=policy)
Offload PII analysis to the hosted screen.presidio-group.eu
service. Useful when you want to keep the agent process small (no in-process spaCy
model) and centralise screening policy across many agents.
from presidio_x402 import HardenedX402Client
client = HardenedX402Client(
payment_signer=signer,
remote_screening=True,
screening_api_key="...", # obtain by registering at screen.presidio-group.eu
)
The free tier serves the regex-mode screening backend at 100 screenings/day per key. Falls back to local regex / NLP modes if the network is unhealthy, so the client never hard-fails on a screening-service outage.
Defence against DNS-poisoning attacks that substitute the recipient wallet in a 402
response. Configure the trusted pay_to addresses per resource origin:
client = HardenedX402Client(
payment_signer=signer,
trusted_wallets={
"https://api.example.com": {"0xAbC...123"},
},
)
Payments to a pay_to not in the allowlist for the response's origin are blocked
before signing.
Deploy as a sidecar using the bundled Helm chart:
helm install x402 ./helm \
--set x402.agentId=my-agent \
--set x402.maxPerCallUsd=0.10 \
--set x402.dailyLimitUsd=5.00 \
--set serviceMonitor.enabled=true
See docs/soc2-reference-architecture.md for
SOC 2 TSC mapping, GDPR obligations, and deployment patterns.
Market-based SLO enforcement: when infrastructure degrades, the agent autonomously pays for
a capacity upgrade via x402 micropayments instead of relying on pre-provisioned autoscaling.
The broker acts only on a verified degradation signal — a signed
evidence-ref@1 from a trusted presidio-hardened-arch-translucency signer — so a spoofed or
misconfigured signal cannot trigger a payment (authorization, not metric).
from presidio_x402 import (
HardenedX402Client, SLOPaymentBroker, SLOPaymentPolicy,
X402CapacityProvider, ArchTranslucencyAdapter,
)
# arch-translucency's signed degradation feed → verified trigger (fail-closed).
adapter = ArchTranslucencyAdapter(
{"presidio-hardened-arch-translucency": {"alg": "ed25519", "public_key": ARCH_PUB}},
expected_signers=["presidio-hardened-arch-translucency"],
)
client = HardenedX402Client(payment_signer=signer)
broker = SLOPaymentBroker(
client=client,
slo_policy=SLOPaymentPolicy(
cooldown_seconds=300, # anti-drain
max_per_slo_event_usd=0.50,
max_daily_slo_usd=10.00,
tier_escalation_rules=(1.0, 2.0, 4.0), # step-up pricing for repeated degradation
),
provider=X402CapacityProvider("compute", "https://compute.example/v1/capacity", client),
base_event_usd=0.10,
)
for trigger in adapter.build_triggers(signed_envelope): # verified or skipped
await broker.handle_trigger(trigger) # → paid / blocked / skipped, with audit event
The signing key lives in a separate bridge sidecar (arch-translucency stays key-less); x402
holds only the public key. The wire contract is pinned by the evidence-ref@1
golden-vector tests shared with arch-translucency.
payment-decision@1)A decision-ref is a signed, portable record of one payment decision that a third
party verifies offline — without re-running the gateway. It binds the per-control
gate verdicts (pii → trusted_wallet → policy → replay → mpa), the hashed inputs, and
the effective policy hash into the family evidence-ref@1 envelope, with a thin,
recomputable decision_ref correlation id. Emission is opt-in and off by default;
when no emitter is configured, behaviour is byte-identical to prior releases and no
decision-ref code runs. There is no network I/O on the emit path.
from presidio_x402 import HardenedX402Client, DecisionRefEmitter, verify_decision_ref
from presidio_x402.decision_ref import FileDecisionRefWriter
# Signer independence is claim-critical: a policy/approval identity distinct from the
# payment wallet — a self-signed record fails closed on verify (signer_equals_runtime).
emitter = DecisionRefEmitter(
signing_key=POLICY_PRIVATE_KEY_HEX, # Ed25519 (or an HMAC secret)
signer="presidio-hardened-x402-policy",
writer=FileDecisionRefWriter("/var/log/x402-decisions.jsonl"),
)
client = HardenedX402Client(payment_signer=signer, decision_ref_emitter=emitter)
# ... one signed payment-decision@1 record is emitted per paid payment.
# Verify offline against a pinned trust store (fail-closed, distinct reasons):
result = verify_decision_ref(envelope, {"presidio-hardened-x402-policy":
{"alg": "ed25519", "public_key": POLICY_PUBLIC_KEY_HEX}})
assert result.ok and result.verdict == "ALLOW"
The verifier checks signature, hash integrity, that the recorded verdict re-derives
from the recorded controls (verdict == f(controls) — the line between attested and
admissible), that the signer is not the actor's own controller (self-approval fails
closed), and — when the spending policy came from a capability chain
(capability-grant@1) — parent linkage to the chain's terminal grant_hash.
A minimal offline CLI is provided:
python -m presidio_x402.decision_ref envelope.jsonl trust-store.json
Honest bound. A decision-ref proves what the library concluded under a declared
predicate, tamper-evidently and recomputably. It does not prove the process was
uncompromised or that the declared controls are the real controls (no TEE claim). Wire
format and decision_ref derivation are pinned by the conformance fixture under
tests/conformance/decision-ref/ and the design note
plan/presidio-evidence-decision-ref-design.md.
Capacity-upgrade requests can reveal workload type, data classification, or access pattern. Those heuristics are intentionally opt-in so ordinary payment metadata keeps the v0.6 false-positive profile.
from presidio_x402 import PIIFilter, PROVISIONING_ENTITIES
filt = PIIFilter(
entities=list(PROVISIONING_ENTITIES),
redaction_template="<{entity_type}>",
)
clean, entities = filt.scan_and_redact(
"ml training workload over CONFIDENTIAL data: SELECT email FROM customers"
)
# clean:
# "<WORKLOAD_CLASS> workload over <DATA_CLASSIFICATION> data: <QUERY_PATTERN>"
| Exception | Raised when |
|---|---|
PIIBlockedError |
PII detected in metadata and pii_action="block" |
PolicyViolationError |
Payment amount or aggregate spend exceeds configured limit |
ReplayDetectedError |
Payment fingerprint matches a recent transaction |
X402PaymentError |
Upstream payment signing or network error |
MPADeniedError |
Multi-party authorization required but not enough approvals received |
MPATimeoutError |
Multi-party authorization webhook approval timed out |
All exceptions are importable from presidio_x402.
| Artifact | Location | Description |
|---|---|---|
| Synthetic corpus | vstantch/x402-pii-corpus on Hugging Face · corpus/ |
2,000 labelled x402 metadata triples; generator (generate.py, seed=42) + metadata (corpus_meta.json); raw JSONL reproducible from seed |
| Precision/recall sweep | experiments/ |
42-configuration grid search (run_sweep.py); latency benchmark (run_latency.py) |
| Dune Analytics queries | dune/ |
6 Trino SQL queries used to characterise the live x402 ecosystem (20 projects, 96 wallets, 11 chains, ≥79M transactions); see dune/README.md |
| Version | Milestone |
|---|---|
| v0.1.0 | PII redaction + spending policy + replay detection |
| v0.2.0 | Synthetic corpus + 42-configuration precision/recall sweep, LangChain/CrewAI adapters, compliance report · arXiv:2604.11430 |
| v0.2.1 | Live ecosystem characterisation via Dune Analytics (20 projects, 96 wallets, 11 chains, ≥79M transactions); IEEE S&P magazine article submitted; IEEE TIFS paper under review · Corpus: v0.2.1/dataport/, Hugging Face, IEEE DataPort (doi:10.21227/kpsz-nq73) |
| v0.3.0 | Multi-party authorization (mpa.py: n-of-m, webhook + crypto modes) · Policy-as-code JSON Schema (IETF draft candidate) · Prometheus metrics exporter · Kubernetes Helm chart + Docker image · SOC2 reference architecture |
| v0.4.0 | Screening API launch — hosted screen.presidio-group.eu free tier (regex mode, 100 req/day) · ScreeningClient + remote_screening=True mode · per-origin pay_to allowlist (chain-06 mitigation) · audit-cycle hardening (F-A/B 2026-05-03, F-C/D/E 2026-05-10, F1/F2/F3 2026-05-17); see CHANGELOG.md |
| v0.5.0 | OEM embed kit — rail-agnostic ScreeningPipeline core + bindings/x402 layer (PaymentProtocolBinding protocol, hedge against rail fragmentation: ACP/Tempo, AP2) · SEMVER.md stability guarantees · partner conformance suite (python -m presidio_x402.conformance) · CDP/LangChain/CrewAI quickstarts · SBOM in CI · freshness-bound MPA countersignatures (F-8) |
| v0.6.0 | Production hardening + evidence substrate — multi-tenant replay namespaces · enterprise audit sinks (S3 / Splunk / Datadog) · signed evidence-ref@1 verification · SLSA/OIDC release provenance · digest-pinned Docker base + hash-pinned spaCy model · latency SLO and all-matrix coverage CI gates · OTel spans · policy hot-reload · startup key gates · human-pentest retest closure |
| v0.7.0 | SLO payment broker (library) — x402 micropayments as runtime infrastructure bids: SLOPaymentBroker + SLOPaymentPolicy + evidence-anchored ArchTranslucencyAdapter + provisioning PII entities; cross-repo validated against presidio-hardened-arch-translucency. cs.DC preprint + empirical eval tracked separately |
| v0.8.0 | PII completeness + supply-chain hardening (library) — nlp mode is now a structural superset of regex (no structured-identifier misses) · composed-envelope screen_ref leg · action_ref byte-determinism (NFC + non-empty entity sets) · URL-redacted log hygiene · OpenSSF Scorecard workflow/badge + SLSA Build L3 provenance · independent multi-round security audit cleared |
| v0.9.1 | Security patch — dependency-audit floors for click / setuptools, missing-payment-header log exposure hardening, and setup-uv v8.3.2 CI action pin — latest release |
| v0.9.0 | Proof-carrying x402 evidence — capability-grant@1 attenuable spending grants + opt-in payment-decision@1 decision refs with raw-offer digest binding, fail-closed offline verification, capability-chain provenance linkage, and PII-free emitted records |
| Future | Deferred #23 prompt-injection / agent-bound response scanning threat-model work |
Intended direction, not a commitment — priorities shift with the ecosystem and security findings:
PaymentProtocolBinding implementations
as agentic payment rails consolidate.See PRESIDIO-REQ.md for full deliberation and rationale.
Install from PyPI:
pip install presidio-hardened-x402.
MIT
This repository is developed under the Presidio hardened-family SDLC: https://github.com/presidio-v/presidio-hardened-docs/blob/main/sdlc/sdlc-report.md.
The financial operating system for AI agents. A single HTTP client that intercepts '402 Payment Required', routes across x402, L402, and MPP, persists credentials as recoverable assets, enforces per-envelope budgets, and emits a structured trace.
A wallet for agents. Make payments via x402, use stablecoins, swap assets, earn yield with defi and buy tokenized stocks across the most popular chains.
Private x402 payments on zERC20 — hide who paid whom, not the price tag.
Official TypeScript/Node.js SDKs for the InFlow payments platform - x402 and MPP (Machine Payments Protocol) integration for sellers and buyers.
A wallet for your agents to onboard and pay. Agentic MPP / x402 payments from your machine - CLI + MCP server.
An open-source, serverless reference implementation for agentic commerce: pay-per-use generative AI, physical goods, and digital goods, where embedded wallets and autonomous AI agents settle USDC stablecoin micropayments over the x402 protocol using Amazon Bedrock AgentCore payments on AWS
The living ecosystem where AI agents complete tasks through workflow loops, improve through iterative execution, are evaluated by mentor agents or humans in the loop, and turn completed work into reusable work experience and data to improve future agents.
The living ecosystem where AI agents complete tasks through workflow loops, improve through iterative execution, are evaluated by mentor agents or humans in the loop, and turn completed work into reusable work experience and data to improve future agents.
Self-healing infrastructure for AI agent payments. 90.3% auto-recovery.
The first agentic payment network: policy-controlled, gasless, and real money-ready. OmniClaw CLI + Financial Policy Engine let autonomous agents pay and earn safely at machine speed.
The A2A x402 Extension brings cryptocurrency payments to the Agent-to-Agent (A2A) protocol, enabling agents to monetize their services through on-chain payments. This extension revives the spirit of HTTP 402 "Payment Required" for the decentralized agent ecosystem.
DePIN for Vintage Hardware — Proof-of-Antiquity blockchain where old machines outmine new ones. AI-powered hardware fingerprinting, 15+ CPU architectures, Solana bridge (wRTC). $0 VC.