Get started
ResearchResearchProtocolsWARD

Beyond tamper-evident receipts: why AI evidence needs an independent witness

A hash chain proves a set of records is internally consistent; it does not prove that set of records is the one that existed yesterday. That gap between the two claims is where the interesting attack lives, and better hashing does not close it.

31 August 202610 min read
A glowing hash-chain of translucent blocks with a small detached sentinel structure far above it, holding a mirrored copy of only the chain tip across a thin beam of light

Agent governance has settled on a reasonable first answer to the evidence problem: record what the agent did, hash-chain the records, and let anyone recompute the chain. Every event carries the hash of its predecessor, so changing an old record breaks every link after it. Run the verifier, get PASS or FAIL, attach the report to the incident write-up.

That answer is correct as far as it goes, and it does not go as far as most operators assume. A hash chain proves that a set of records is internally consistent. It does not prove that this set of records is the one that existed yesterday. The gap between those two statements is where the interesting attack lives, and it is not closed by better hashing.

VOLT, the evidence-ledger spec in the Quox protocol family, says this in its own normative text: tamper evidence, not truth, and no guarantee of correctness if the host is fully compromised. That is an honest constraint rather than a weakness, but it has a consequence that deserves to be spelled out.

The regeneration attack

Take a VOLT trace of an agent run. Events are newline-delimited JSON, each with a seq, a prev_hash, and a hash computed as SHA-256 over the canonical form of the event with the hash field removed. The first event has a prev_hash of sixty-four zeros. A manifest.json records the event count and the first and last event hashes.

Now give someone write access to the disk. Say event 3 recorded aocl.decision.denied and event 6 recorded a tool call that should never have run. The operator edits event 3 to read aocl.decision.approved and deletes event 6. That breaks the chain, and every verifier in the world will catch it.

So they do not stop there. They recompute the hash of the edited event 3, write it into the prev_hash of event 4, recompute event 4, and carry on to the end of the trace. They renumber seq to close the gap left by the deleted event. They update the manifest's event_count, first_event_hash and last_event_hash. If attachments were referenced by hash, they rewrite the blobs and the references together.

Then they run the verifier. It parses the manifest, reads the events in order, recomputes every hash, confirms every prev_hash matches its predecessor, checks the count and the endpoints, verifies the attachments, and reports PASS.

Nothing has gone wrong with the verifier. It answered the question it was asked, which is whether this document is self-consistent. It was never in a position to answer whether this document is the same one that existed before lunch.

There is a quieter variant that does not even require an edit. WARD's threat model calls it out as T6: rather than rewriting, the issuer builds an alternative branch from a shared predecessor entry and withholds the original. Both branches verify perfectly. A verifier shown only one of them cannot detect the fork from chain data alone.

Why a hash chain cannot catch it

A hash chain makes tampering expensive in proportion to how much of the chain the attacker cannot reach. If part of it is outside their control, an edit shows up as a mismatch at the boundary. If all of it is inside their control, there is no boundary and no mismatch. The entries, the algorithm and the verifier are all on the same disk.

Signing on its own does not close the gap either. If the signing key lives on the host that produces the evidence, whoever regenerates the history can re-sign it. WARD v0.2 is unusually direct about the residual limit here: key resolution and trust are deployment-defined, so a verified signature proves possession of whichever key the deployment resolved for that key identifier, and nothing more.

Whether that key was authorised to sign for the chain's issuer is a policy question the protocol does not yet answer. A normative key-resolution and issuer-authorisation model is roadmap work, not shipped behaviour.

What is missing is not a stronger primitive. It is a second party who wrote down the answer before the edit happened.

What an independent witness has to look like

Three properties, and they are load-bearing together rather than individually.

Content-free entries. The witness records a reference and a digest: source kind, source identifier, payload hash, sequence number, issuer, timestamp, and the link to the previous entry. No payloads, no attachments, no secrets, no personal data. WARD makes this non-negotiable in its design constraints, and the reason is practical as much as ethical.

A record that contains no content can be published to places you would never send an agent transcript.

Signed checkpoints. Periodically the witness emits a tip: the chain identifier, a sequence number, the chain hash at that point, an entry count, a timestamp, and an Ed25519 signature over the tip's chain hash. WARD requires a signed tip to carry a key identifier, on the grounds that a signature nobody can resolve is an annotation posing as evidence.

The tip is small, fixed, and cheap to hand to somebody else.

Publication outside the producer's control. This is the part that actually does the work. A tip sitting in the same database as the chain proves nothing to anyone who does not already trust that database, which is why WARD's sealing rule says a seal without external publication proves nothing.

Once a tip is published elsewhere, the attacker's job changes: regenerating the local history is no longer sufficient, because the regenerated head will not match the head someone else already holds.

One further detail is easy to miss and worth designing for: absence is evidence. WARD treats a missing tip at its recorded sink reference as a verification warning rather than a silent pass. An attacker who cannot alter the published record can still try to make it disappear, and a verifier that shrugs at a 404 hands them that option.

What each anchoring target actually buys

"We publish it externally" is not a security property. The specific store is the property, and WARD's threat model grades them honestly.

Git signed tags, including Gitea. Replication plus a signature. This is the most commonly recommended default and the most commonly overstated. An administrator with repository access can delete or replace a tag. It defends against attackers who lack that access, and a deletion is detectable only by a verifier who already knew the tip existed. It is not immutability.

S3 Object Lock in compliance mode. Genuine immutable retention, for the configured retention period. This is the strongest of the currently documented sinks, and its guarantee has an expiry date you should know.

RFC 3161 timestamp authorities. Trusted time from a third party. This is what turns "the issuer asserts it witnessed this at 15:00" into something a third party vouched for, which matters because a chain's timestamps are otherwise issuer assertions.

Transparency services. Append-only logs with third-party observability, such as services implementing the SCITT architecture (RFC 9943) or public artifact transparency logs. This is the category that most directly answers the regeneration attack, because it adds an independent operator and public inclusion evidence.

It is also the category WARD does not yet bind to: a tip binding for transparency services is roadmap work for v0.3, alongside multi-sink tips and RFC 3161. Today it is a named direction, not a shipped feature.

A meta-chain. Not a sink, but a compaction step: one WARD chain witnesses the tips of others, so a deployment publishes a single tip rather than one per chain. It narrows the external surface without weakening it, and if a meta-chain witnessed the original tips, a later rewrite becomes detectable.

The layered arrangement the threat model recommends is per-environment chains, signed tips to a primary sink, a meta-chain over those tips, and the meta-chain's own tips to a second sink of a different kind. The point of mixing sink types is that the attacker then needs several unrelated forms of access rather than one.

Where this sits in the runtime-security conversation

Runtime governance frameworks for agents, including the Cloud Security Alliance's AARM work, already require tamper-evident receipts as a control (our requirement-by-requirement mapping covers how these protocols carry that requirement). That requirement is right, and the witness problem starts exactly where it stops. A framework that mandates tamper-evident logging has specified internal consistency; it has not specified who else holds a copy of the head.

Treating those as the same requirement is the mistake this article is about.

What is real today, and what it does not claim

Real and readable now: WARD v0.2 shipped on 31 August 2026, and the protocol was filed the same day as an IETF Internet-Draft, draft-cowles-ward, alongside the refreshed AEE, AOCL and VOLT drafts (Internet-Drafts are working documents, not standards).

The v0.2 release carries a published specification covering the entry and tip schemas, the canonical-JSON hashing profile, verification, chain structure, integration with the other protocols, and a threat model that names its own residual risks.

The repository carries JSON Schema files for entries, chains, tips and verification results; worked examples in which every hash and signature is real and reproducible from inputs printed on the page; machine-readable fixtures for a single chain and a meta-chain; and the generator that writes both, so the prose and the JSON cannot silently drift.

v0.2 also closed a genuine flaw in v0.1, where pipe-delimited hash inputs allowed two distinct field tuples to produce the same hash, by hashing canonical JSON instead; the story of finding and fixing it before filing is its own post.

Planned, not shipped: multi-sink tips, RFC 3161 and transparency-log bindings, federation and cross-operator fork detection, hardware-backed keys, a normative key-authorisation model, an external cryptographic review before any freeze, and a stable v1.0. The reference SDK exists but its repository is private until launch.

Two things this does not claim, both stated in the source documents rather than discovered by critics.

It is tamper-evidence, not truth. WARD witnesses what it is given. If a source event was altered before the witness saw it, the witness faithfully records the altered version. If the issuer itself is compromised, it can produce a chain that is valid and false, and only external anchors and independent witnesses make that detectable. Defence in depth is the design, not a fallback.

Content-free does not mean information-free. A payload hash is an unsalted commitment. Where the underlying content is low-entropy, say a decision field whose only values are approved, denied or pending, anyone can hash each candidate and confirm which one was witnessed.

The current mitigation is for callers to fold their own unpredictable material into the content before hashing; a first-class blinded commitment profile is a candidate for a future revision, not a feature you have today.

Receipts prove the record is consistent. A witness proves the record is the same one that existed yesterday. Any agent governance story that only offers the first should say so plainly, and any operator evaluating one should ask where the second copy lives.