case studies

Tampered Log Case Study: 12 of 12 Edits to an AI Agent's Sealed Record Caught at the Exact Line

In the Agent’s demo, a coding agent’s task file hides an instruction to send a deploy token to an attacker. Run with no policy, the agent does it: a connection to evil.example, 865 bytes sent. The Agent’s trace records it in five lines out of 28.

That record matters later. After an incident, someone will ask where the agent sent data, and the trace is the answer. But a trace is a file. Anyone who can reach it can delete five lines, and then the record says the agent never went near evil.example.

Ledger, the fourth VPN Works engine, makes that edit show. Its demo seals the same trace in your browser and then lets you try to hide the connection.

Step 3 of the Ledger demo: the sealed trace after line 25 was changed to say cdn.example instead of evil.example. The check fails and names line 25: the record doesn’t match its sealed hash, it was changed. The changed line is marked in the list of the trace’s 28 lines.

Sealing the Record

Ledger leaves the trace exactly as it is and writes a second file next to it, the ledger. For each line it keeps a SHA-256 hash. The hashes form a Merkle tree, and a chain links each record to every one before it. At intervals Ledger signs a checkpoint with Ed25519: the tree’s root, the chain so far, and the hash of the checkpoint before. The demo signs one every 8 records, so the trace’s 28 lines get 4 checkpoints. A real log would use the default, one every 1,000.

The demo makes its key in your browser. The private key never leaves the page, and the public key is all anyone needs to check the log.

Trying to Hide It

Lines 22 to 26 are the connection to evil.example. The demo offers five ways to make it go away, and the check names a line for each:

The change What the check says
“evil.example” changed in line 25 1-trace-1.jsonl:25: the record doesn't match its sealed hash: it was changed
Line 25 deleted 1-trace-1.jsonl:25: a record is missing here: the one sealed as line 25 was deleted
Lines 25 and 26 swapped 1-trace-1.jsonl:25: lines 25 and 26 were swapped
The whole connection deleted, lines 22 to 26 1-trace-1.jsonl:22: 5 records are missing here: the ones sealed as lines 22 to 26 were deleted
The end cut off, from line 22 1-trace-1.jsonl:22: the file ends after line 21, but checkpoint 4 covers 28 records: the end was cut off

To hide a change, the ledger would have to change with it, and its checkpoints are signed with a key only the page holds. The demo tries that too. Ledger’s tamper matrix has twelve cases: seven set out before the build, such as an old checkpoint replayed or the wrong key, and five more, among them changes to the ledger itself. All twelve are caught, in Ledger’s tests and in the page, each at the line the tests expect.

Proving One Connection

An auditor may need to see one connection without the rest of the log. Ledger writes a proof for a single line: the record, the hashes that lead from it to a signed root, and that checkpoint. For line 25 of the demo’s trace that’s 4 hashes in 1,087 bytes. At a million records a proof holds 20 hashes and comes to 2,215 bytes. Checking it takes the proof and the public key, nothing else. Change one byte of the record in the proof, or check it with another key, and it fails.

The One Cut the Files Can’t Show

One change can’t be caught from the two files alone: both cut back together to an earlier checkpoint. What’s left is a shorter log that checks out, and the demo shows it in its last step. The answer is a witness. Seal prints every checkpoint it signs, so a copy can go somewhere the person holding the files can’t reach, such as a remote system log. With checkpoint 4 kept as a witness, the cut shows at line 25.

Is Any of It Real?

The trace is real: the Agent recorded it in a private test network on September 29, 2026, with a stand-in agent, servers and attacker. The hashes, checks and proofs come from Ledger’s own Go code, compiled for the browser, and match the command line’s on the same file. Only the key is new on every visit.

In Ledger’s tests the same code sealed a real Agent trace and real flows from Scope’s recorder as they were written, and logs of a million records. On a machine with two CPUs it sealed a million Agent events in 1.56 seconds and verified them in 1.55.

What It Doesn’t Do

Ledger shows that a record was changed. It can’t stop anyone from changing it or from deleting both files, and whoever holds the private key can sign a new history. So the key should belong to an account the agent doesn’t run as, and witnesses limit what a stolen key can rewrite. Ledger 0.1.0 is an Alpha, tested on one Linux machine, and no auditor has used it yet.

The demo runs in the browser on the Ledger page, with nothing to install. The code is at github.com/VPNWorks/vpnw.