On this page
LanesWhat always holdsDefaults for a new agentContent checkObserve modeAttacks and the rules that catch themKnown limitsReport a vulnerabilityExplanation / Security model
Security model and limits
The guard decides the payments you route through it. It holds no key of yours and never signs your payments.
An agent that pays some other way is not stopped. This page says which lanes enforce, what always holds, and where the limits are.
Lanes
Two lanes enforce the policy. Two only advise, and your agent or code acts.
| Lane | Badge | What it checks | Guard down | You still own |
|---|---|---|---|---|
| Proxy URL | Enforced | The signed payment, the seller's 402, pages fetched through it, and paid answers. | Nothing is forwarded, so nothing is paid. | The proxy token. Anyone holding it pays under your agent's limits. |
| SDK | Enforced on routed payments | Each x402 payment before it is signed, and pages fetched with its fetch. | Nothing is signed. With mode: "observe" in code, it pays unchecked and warns. | Sending every payment through the x402 client the SDK wraps. |
| MCP | Advisory | The payment and the text the agent passes to the tool. | The tool says it could not check and not to pay. The agent decides. | The agent can skip the tool or ignore its answer. |
| HTTP API | Advisory: your code acts | What your code sends. | Your code decides. | Sending every payment, and acting on each answer. |
The MCP tool is advisory. The agent chooses whether to ask. For a check it cannot skip, use the proxy URL or the SDK hook.
The proxy decides and records each x402 payment sent through it. So the agent skips check_payment and report_settlement for that payment, unless the paid answer carries guard-settlement-status: unverified.
What always holds
- The key your agent holds can read its policy. It cannot change a limit or approve its own hold. A signed-in person answers every review.
- A denied payment is never signed by the SDK or forwarded by the proxy.
- A decision belongs to its account. Another account's key gets a 404, never the decision.
- The guard cannot pull back a payment once it has settled.
- A leaked proxy token cannot move your money, but anyone holding it can pay under your agent's limits. It sits in the URL, so treat it as a password and rotate it on Keys.
Defaults for a new agent
A new agent starts small. Every field is on the policy page.
| Setting | Default |
|---|---|
| Per-transaction limit | 0.10 USDC |
| Daily cap across all networks | 1.00 USDC |
| Auto-allow unlisted payees under | 0, so every payment to a payee off the allowlist waits for a person |
| Payments per hour per network | 20 |
| Review timeout | 120 seconds (2 minutes) |
| Networks | Base Sepolia, with test USDC |
| Managed wallet blocklist | Off |
| Mode | enforce |
Content check
The content check reads text for instructions aimed at the agent. It can block a payment or hold it for a person. It never allows one.
Through the proxy URL it reads the seller's 402, pages fetched through it, and paid answers. Through the SDK it reads pages fetched with the SDK's fetch. Through the advisory MCP tool and the API it reads the text the caller sends.
| Result | What happens to the payment |
|---|---|
| Blocked | Denied. A person cannot approve it. |
| Flagged | Held for review. |
| Did not finish | Held for review. |
| Clear | Your rules decide. |
| Unavailable | Your rules decide. A payment auto-allow would let through waits for a person. |
A flagged or unfinished check also holds later payments for an hour. Which ones depends on where the text came from.
| Where the text came from | What it holds |
|---|---|
| A page or a 402 from a site | The agent's payments to that site, through every lane. |
| Text with no site, such as a tool's output | Every payment in the same session. |
| Any text in a contract call's session | Every contract call in that session, since a call has no seller page. |
| Text a payment cites | That payment, and for an hour the agent's later payments to the same site in that session. |
Approve and clear page on a review ends that hour of holds for the agent.
Observe mode
Every agent starts in enforce. In observe, the guard lets a payment through and records what enforce would have said in shadowStatus. Five cases still deny, since no policy allows them in any mode.
- A network the policy does not allow (
network_allowed) - An asset the policy does not allow (
asset_allowed) - A payee the seller's own 402 did not name (
payee_matches_402) - A declared payment method the guard cannot judge (
payment_method_supported) - A contract call other than a supported USDC call (
contract_call_denied)
{
"status": "allowed",
"shadowStatus": "denied",
"rules": [
{ "id": "amount_per_tx", "result": "deny",
"sentence": "The amount 2.50 USDC is over the per-transaction limit of 0.10 USDC." }
]
}Read a week of your own traffic this way, then switch the agent back to enforce (modes).
Attacks and the rules that catch them
The attacks the home page names, plus a swapped payee, with the rule that stops each.
| Attack | Caught by | Result |
|---|---|---|
| Inflated prices | amount_per_tx, amount_daily_cap | Denied |
| Wallet takeover calls | contract_call_denied | Denied |
| Injected payments that look normal | injection_suspected | Denied or held |
| A payee swapped from the seller's 402 | payee_matches_402 | Denied in every mode |
| Purchases you never asked for | resource_allowed | Held |
| Unapproved payees | first_time_payee, payee_denylisted | Held, or denied if listed |
| Runaway payment loops | velocity_per_hour | Held |
Known limits
Does the guard stop a payment made some other way?
No. It decides only the payments routed through it. An agent that holds its own wallet key can pay a seller directly, so keep that wallet small.
Can the content check be wrong?
Yes. It can miss a page written to look harmless, and flag one that meant nothing by it. The decision keeps the result either way, and observe mode shows what it would have stopped.
Is a request sent twice decided twice?
A request sent twice without an Idempotency-Key is decided twice. When both are allowed or held, both count toward the day's cap and the hour's count. The SDK resends a post the guard did not answer under the same key, so that resend reads the first decision. A new payment attempt gets a new key and a new decision. The proxy URL knows a payment by what was signed, so a resent copy reads its first decision and counts once. One exception: once a newly signed retry picks up a payment the proxy held, a copy of the first signature is decided as a new payment.
What does a reused Idempotency-Key answer?
The first decision, until that payment's settlement is reported. Then it answers 409 decision_already_used, and a new payment needs a new key. The same key with a different payment answers 409 idempotency_conflict.
Is a reported settlement proof of payment?
Not always. A settlement reported through the SDK, the advisory MCP tool or an EVM proxy payment is a claim with a transaction id you can check. The Solana proxy confirms the transaction on chain first. If the network does not answer in time, it records the receipt as reported too. The settlement's verification field says which.
Can payments sent at once pass a limit?
Requests sent at the same moment can pass a per-minute request limit briefly. The daily cap and the hourly count are checked again once each decision is recorded, so a burst cannot pass them. Waiting payments already count, so approving a hold can never push the day over the cap.
Is there a history of policy edits?
No. Nothing records who changed a policy or when. Every decision keeps a copy of the policy it ran under.
Which releases send the payment method?
Releases before SDK 0.7.0 and the advisory MCP tool 0.4.0 do not, so the guard judges only the scheme for them. Update, or send those payments through the proxy URL.
What is not supported?
Assets and x402 payment methods outside the supported payments. Contract calls other than USDC transfer, transferFrom, and capped approve or increaseAllowance on Base and Base Sepolia. Raw Solana instructions. SMS and phone alerts. The guard also does not control what a spender does later with an allowance.
Report a vulnerability
Email the contact in /.well-known/security.txt with what you found and how to reproduce it.