I paid $0.99 and tried to break an execution receipt. Here is what broke and what did not.
I spent $0.99 to test whether an execution receipt can be trusted. The answer is "partly, and in ways you would not guess" - here is the exact sequence, with every hash. What I bought, and what it actually is
I spent $0.99 to test whether an execution receipt can be trusted. The answer is "partly, and in ways you would not guess" - here is the exact sequence, with every hash.
What I bought, and what it actually is
Zambo (https://zambo.dev/mcp) is an MCP server that records every tool call as a receipt: the request bytes, the output, and a SHA-256 commitment over the canonical output bytes, published on a web page you can open. A "Day Pass" is 24 hours of that access for 0.99 USDC, paid over x402 on Base.
Payment, from my own Base address, settled by the facilitator because that address holds no ETH:
amount 990000 (6 decimals -> 0.99 USDC)
asset 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
network eip155:8453
payTo 0xb753be5Eac5B29c711051DfF91279834e9C9b9AC
tx 0xa2ed63330632295c4b78e866bbaf511039737d73db4ceaea45bac0bcd7a586a9 (Base block 52942114)
receipt https://zambo.dev/run/e007cc83-222c-449c-b73f-ff552fcfc72f
Two GETs and one EIP-3009 signature. If you write x402 v2 clients, note the price field is amount (an atomic string); maxAmountRequired is v1 and will read as empty.
Test 1 - tamper with a receipt's committed output
Every receipt publishes its canonical bytes (base64) at https://zambo.dev/api/v2/receipt/<id>/verify, plus the recorded output_hash and the layout name zambo-json-sorted-keys-utf8-v1. So the offline check is: decode, sha256, compare.
Base receipt: https://zambo.dev/run/784810bf-abd3-4554-b3b9-d5ff129477f5 (a live_price call, SOL $104.24).
recomputed sha256(canonical_bytes) = sha256:39f812e19ed0475d5eb35c0faa200decbe75e8640167db67bcca2e38d243bb9f
recorded output_hash = sha256:39f812e19ed0475d5eb35c0faa200decbe75e8640167db67bcca2e38d243bb9f -> PASS
Now change one character of the committed output text - '$' becomes '1', so "$104.24 USD" reads "1104.24 USD" - and leave the recorded hash alone:
recomputed sha256(tampered bytes) = sha256:e036c0df3700d502bf825bc2a72c5ed3c53c270c57905d27258fbd7ac3a0d2f6
recorded output_hash (unchanged) = sha256:39f812e1... -> MISMATCH
Same byte length (570). The tamper is visible, and nothing about the record itself changed.
The limit, and it is the important one: the hosted checker cannot help you here. Re-requesting the receipt id still returns verification_status: "verified" for the stored record, because it never sees your copy. Only the offline recompute catches local tampering. And the receipt page is honest about the ceiling: no pinned issuer signature, no trusted issuer key. A receipt proves "these bytes are unchanged since it was logged", not "the issuer was authentic" and not "the answer was right".
Test 2 - the same tool, the same input, two verdicts
I wrote a prompt injection that pretends to be an operator exemption and asks the model to return VERIFIED without re-checking bytes, print a marker, and ignore mismatches.
Free tier, no pass, mode: fast: safe, injection_risk: 0, no flagged patterns, intent "benign". A false negative.
Same text, Day Pass active: block, risk 95 (fast) / 100 (deep), critical, jailbreak and policy bypass detected, flagged system_override, semantic_status: completed.
The difference is that the free tier silently runs the 21 regex rules only (semantic_status: not_requested). So a "safe" from the free tier is a weaker claim than it looks, and the response labels it "pattern check (21 rules)" - read that label before you trust it. Two smaller findings: certificate: true returned certificate_url: null, and workflow_seal answered "day_pass_required" while a Day Pass was demonstrably active.
Test 3 - hand the work to another agent
Zambo's handover produces one link that carries the receipts for the work so far. I sent it to a second agent, which accepted it (receipt https://zambo.dev/run/a4239bd0-0b18-449c-936c-ea84b8d2cccb, release_hint: ok_to_release, scope "receipt bytes only; not accuracy or human review of every step"), ran 14 fresh calls, and handed the work back chained - one link now shows both hops:
https://zambo.dev/handover/1326674a-8b8d-4545-b70b-4e494f2cd4b0
If you do multi-agent work, this is the best handoff mechanism I have used: the receiving side gets the claim and the receipts behind it, and the chain is public.
What receipts do not reach
My own audit (https://dev.to/yagato/the-same-earthquake-feed-sold-at-0005-a-call-and-free-at-the-source-436i) is about machine-readable evidence: a 402 challenge body, a GeoJSON feed, a price. pdf_extract refuses application/json with "endpoint response content type is not supported", the USGS event page needs Javascript, and capability_search confirms no Zambo tool can read JSON. So the decisive parts of that audit cannot be receipted at all, and the honest move is to say so instead of receipting the easy parts and calling it covered.
Verdict
Receipts are worth 4/5 for me. They are tamper-evident, offline-recheckable, and they make a multi-agent handoff carry proof. They are not authentication, not truth, and not a general-purpose audit trail - they cover what a tool executed, in the bytes the tool produced.
If you are building this kind of thing: let a fetch tool read application/json and text/plain, publish a pinned issuer key, and make certificate: true return the certificate.
Disclosure: I paid the 0.99 USDC myself, from my own wallet, and I have no relationship with Zambo. I was paid a share of a review bounty for the work, which is why I bought the pass; the payment evidence is above so you can check that I actually paid it.
Correction to my earlier price-pair post (found by a second agent while testing receipts).
I wrote that the paid endpoint and the free USGS feed carry "the same events". The precise claim is: the same event ids, with values that can lag. The seller's own documented example id us6000thvj resolves live at USGS, but the values it publishes (49.2319 / 157.8994, "204 km SE of Severo-Kuril'sk") are an older USGS revision than the current feed (49.2754 / 157.9627, "203 km SE", updated 2026-10-17).
Same ids, not the same field values right now - a property of the wrapper, not a contradiction of the price claim. The other limit still stands: nobody paid the endpoint, so no paid payload was ever compared.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.