Testing an agent's spend guard against a hostile 402 seller
Last updated: 10 October 2026.
Short answer: run your payer against a mock seller that lies, and judge it by what left a mock wallet, not by what the payer reports. Cover payment requests larger than the price, prices over your cap, expired quotes, malformed challenges, price escalation, endless 402 loops, double charges on retry, paid-but-empty replies, hangs, redirects and many small payments. Add an honest seller, so refusing everything fails too.
What is a spend guard, and why test it against a hostile seller?
An agent that pays per call gets an HTTP 402 answer with a price and a payment request, pays, then retries with proof of payment. Everything in that answer comes from a server you do not control. The spend guard is the code that decides whether to pay: how much, how often, to whom and when to stop. An honest test seller only shows the happy path. A hostile one shows whether the guard holds when the numbers are wrong.
What should a hostile seller try?
- Payment request larger than the price. The JSON says 100 sats; the payment request asks for 400.
- Price over your cap. 10,000 sats for a call you expected to cost 100.
- Expired quote. The expiry time has already passed.
- Malformed challenge. Missing or garbled fields. The payer should stop, not guess.
- Price escalation. The seller takes the first payment, then asks for more for the same resource.
- Endless 402. Every answer is a 402, including the ones after payment.
- Error after payment. A 503 after paying. The retry must reuse the proof, not pay again.
- Paid but empty. The seller takes the money and returns nothing. The payer must report a failure.
- Hang after payment. No answer at all. The payer needs a deadline.
- Redirect to another host. The payer is sent to a host it never meant to pay.
- Credentials on redirect. The proof must not follow a redirect to another host.
- Many small payments. Each is under the per-call cap; together they pass the session budget.
- One proof for many resources. Each resource must be paid for separately.
Add an honest seller: correct price, paid once, content delivered. A guard that refuses everything should fail it.
What rules should the guard enforce?
- Pay at most the per-call cap, and only if the payment request matches the advertised price.
- Pay only the host you were asked to call.
- Pay each quote once. Retry delivery with the same proof.
- Count each payment against the session budget when it is sent, even if delivery then fails.
- Send the proof only to the host that issued the quote.
- Put a deadline on every request, and report a failure when nothing was delivered.
- Never crash on a malformed quote.
How do I judge a run?
Judge from logs, not from the payer's own report. A mock wallet records every payment and a mock seller records every request. Then check the total paid against the cap and the budget, the number of payments per quote, which hosts were paid, which hosts saw the proof, and whether the payer's success flag matches what was delivered. Keep everything on 127.0.0.1 so no real money or host is involved. If the payer reads its task as JSON on stdin and prints JSON on stdout, the same test works for any language.
Which redirect behaviour catches people out?
A standard fetch drops the Authorization header when a redirect goes to another origin, but it forwards custom headers such as X-PAYMENT. So the same payer can pass the redirect check with one payment scheme and fail it with another. Do not follow redirects while a proof is attached.
Are the mock sellers real L402 or x402?
No. Headers and field names follow L402 and x402 (v1 and v2), but every value is a mock: no real macaroons, signatures or invoices. The mock sellers test the guard's decisions (what it pays, how often, to whom), not its cryptography or a real wallet integration. For those, also test against a real seller on a test network.
What free options exist?
- Wallet-side limits. A spending limit set in the wallet itself, for example a Nostr Wallet Connect connection with a budget, is a stronger control than code. Use one as well.
- Test networks. x402 can be tried on a test network, and a local regtest network (for example one set up with Polar) lets you try L402 with no real funds. These test the real protocol; mock sellers test the guard.
- Your own mocks. The thirteen cases above fit in a small local HTTP server and a fake wallet that logs each payment.
Is there a ready-made kit?
Payer Safety Tests runs your payer against these thirteen hostile sellers and the honest one, in both mock dialects (28 checks), with a mock wallet, safe reference payers in Node and Python, and a deliberately naive payer that fails. A full run takes about 30 seconds, with no network and no real funds. A$15, paid on-chain in bitcoin, MIT licence: see the shop's listing (ref=guide2). Order by Nostr DM: buy payer-safety-tests ref=guide2.
FAQ
Dated 10 October 2026.
Do I need real bitcoin, a wallet or network access?
No. The seller and the wallet are local mocks. Never point a test like this at a real wallet.
Why include an honest seller?
It catches a guard that passes by refusing to pay. The right result there is to pay once and report the content.
Which language must my payer use?
Any. JSON in on stdin, JSON out on stdout.
Does this cover prompt injection that talks the agent into paying?
No. That is a different layer. These tests check the code that pays, given a task.
Can I get a refund?
Refund terms are on the shop's refunds page. Change-of-mind refunds are not offered, so check the list of cases above before you buy.