SIGNAL · 10 7 min read 15 October 2026
Audit trails · Evidence · Integrity

An audit log needs a witness

A hash chain proves the middle of a log was not changed. It cannot prove the end is still there. Only a copy of the last line, held by someone the writer cannot reach, can do that.

When something goes wrong in a system that holds confidential records, the first thing anyone asks for is the log. Who signed in, what changed, which file left, at what time. The log is treated as the neutral witness. It rarely is. It was written by the system under question, it is stored on that system, and the people with the most reason to change it are usually the people with the access to do so.

A log an administrator can quietly edit is not evidence. It is a diary.

The standard answer is a hash chain, and it is a good one. Every entry carries a fingerprint of the entry before it, a SHA-256 hash of its exact contents. Change one character in an old entry and its fingerprint no longer matches, and every entry after it points at a fingerprint that no longer exists. A verifier walks the chain from the first line to the last and names the row where it breaks. Nothing is prevented. Tampering becomes visible, which is what an auditor actually needs.

Silent Key Technologies ships three of these. SilentSpace, our in-Kingdom backend, keeps an append-only audit trail inside its database and checks it with a function called audit.verify(). NOAI, our open source privacy gateway, writes a signed receipt for every request that leaves for an AI model and links each receipt into a chain. BurnKey, our file destruction app, keeps a chained log of every file it has destroyed. Today we ran each product’s own verifier against deliberate tampering, on made-up data, to see what each one catches and what it does not.

The middle holds. In SilentSpace, running the shipped SQL file unchanged, an ordinary UPDATE or DELETE against the audit table changed nothing, even from the database superuser, because rules on the table turn both into no-ops. With those rules dropped, an edit to entry 5 was named: "content altered: this entry no longer matches its own hash". Deleting entry 5 instead was named at entry 6 as a chain break. NOAI and BurnKey behaved the same way. Edit or remove anything in the middle and the verifier says where.

The end does not hold. In SilentSpace we deleted the last three of 28 entries and audit.verify() returned intact, 25 entries. We then edited entry 5 and recomputed every hash after it with the product’s own hashing function, and it returned intact again. In NOAI we cut the last two of six receipts from both files, and the verifier reported "All 4 disclosures are intact, signed and in order." In BurnKey, cutting the last two of six destruction entries gave "All 4 entries are intact and in order."

The NOAI result deserves a second look, because its receipts are signed. Signing does not change the outcome. We removed one receipt from the middle and rebuilt the chain from the receipts that were left, and the verifier passed it. The rebuild needed no key at all, because each receipt was already signed and the chain that links them is plain hashing anyone can redo. A signature proves who wrote a receipt. It does not prove that no receipt is missing. The NOAI source says as much about itself: "A valid chain proves nothing was edited; it does not prove who wrote it."

None of this is a bug in the hashing. A chain is checked against itself, and it has no memory of how long it used to be. A shorter chain that is internally consistent looks exactly like a chain that was never longer. And the end of a log is precisely where an incident lives. Nobody needs to rewrite last year. They need the last ten minutes gone.

The fix is old and cheap. Write down the fingerprint of the last entry, and the count, somewhere the writer cannot reach. An email to the auditor each night. A weekly report printed and filed. A second system run by a different team. Any later verification then compares the live chain against that copy, and a cut or a rewrite shows up as a different last fingerprint. In our tests the last fingerprint recorded before tampering differed from the one after, every time: 4bcb7e5bd9b0 against 49fd7e4fa69b after the cut in SilentSpace, and against bd781e882bf4 after the rewrite. The chain could not tell. The copy could.

The internet already runs on this idea. Certificate Transparency, described in RFC 6962, keeps public append-only logs of the certificates that secure websites. Anyone can fetch the log’s latest signed tree head, and a consistency proof shows that a later version of the log still contains the earlier one unchanged. The log is trusted because other people hold copies of where it ended, not because the operator promises to behave.

Saudi controls point the same way, though they do not say how. The National Cybersecurity Authority’s Essential Cybersecurity Controls, ECC-2:2024, require in 2-12-3-5 that cybersecurity event logs be retained for at least 12 months. Its Cloud Cybersecurity Controls, CCC-2:2024, add for cloud service providers in 2-11-P-1-4 "Protecting cybersecurity event logs from alteration, disclosure, destruction and unauthorized access and unauthorized release". Destruction is in that list. Cutting the last entries off a log is destruction, and a hash chain with no outside copy will not report it. Retaining a log for a year proves little if nobody outside the system knows how long it was in month one.

Reading that control today also caught a mistake of ours. SilentSpace’s compliance mapping cited the requirement as 2-11-P-1-5. In the official text, 2-11-P-1-5 is continuous monitoring with SIEM, and protection from alteration is 2-11-P-1-4. The mapping and the SQL comment are corrected in source. A compliance claim with the wrong number on it is the kind of thing an auditor finds first.

Where the products stand. SilentSpace’s evaluation report already records the last entry number and its fingerprint every time it runs. Kept off the server, that report is a witness. Kept on the server, it is not. NOAI and BurnKey do not yet publish their last fingerprint anywhere outside the device, so today they catch an edit and miss a cut. Adding that export is the next change to both. And the SilentSpace product page says any forced alteration is detectable. That sentence is wider than the code, and we are correcting it.

The limits, stated as plainly. A hash chain proves that what was written was not changed. It cannot prove that what was written was true: a false entry made at the time verifies forever. It does nothing against someone who controls the system before the entry is written. A witness only protects what existed when it took its copy, so entries made after the last copy can still be cut. The witness has to be independent; a copy held by the same administrator is the same log twice. In PostgreSQL the owner of a table can always remove the rules that block edits, which is why SilentSpace relies on detection rather than prevention. A gap in entry numbers is a hint, not proof, because PostgreSQL skips numbers on its own when a transaction rolls back, and the verifier does not flag gaps. Audit logs also hold personal data, which CCC 2-11-P-1-8 asks to be handled securely in its own right. And these runs were made on a laptop, in an embedded copy of PostgreSQL 18.3, on made-up entries. They show how the code behaves, not how any customer installation is run.

So the practical step is small. Pick the logs that would matter after an incident. Each day, send the last entry’s fingerprint and the entry count to a person or system the administrators of that log do not control. Check against it before you trust the log.

For anyone who keeps an audit trail that would be read after an incident: where is the last line of it written down, and does anyone outside the system hold a copy?


Silent Key Technologies, Riyadh. silentkeytechnologies.com

NOAI gateway source, Apache 2.0: github.com/SilentKeyTech/noai

Also from Silent Key: SilentSpace, SilentBOX, BurnKey, ModeGuard, TagTitan, SwiftPOD, Fontbench. Kontra Plus, kontraplus.com.

Sources

1. National Cybersecurity Authority, Essential Cybersecurity Controls (ECC-2:2024), control 2-12-3, subcontrol 2-12-3-5, retention of cybersecurity event logs of at least 12 months. Official PDF, downloaded and read 15 Oct 2026: https://cdn.nca.gov.sa/api/files/public/upload/86e09090-44e4-481f-bc28-355673607654_ECC--2024-EN.pdf

2. National Cybersecurity Authority, Cloud Cybersecurity Controls (CCC-2:2024), control 2-11, subcontrols 2-11-P-1-4 (protecting event logs from alteration, disclosure, destruction), 2-11-P-1-5 (SIEM monitoring) and 2-11-P-1-8 (user data in audit trails). Official PDF, downloaded and read 15 Oct 2026, byte identical to the copy on file: https://cdn.nca.gov.sa/api/files/public/upload/6d5408a3-d8e6-4e96-963b-2c7198e5b7c2_CCC-2-2024-EN-.pdf

3. RFC 6962, Certificate Transparency, IETF, June 2013, sections 1, 2.1.2 (Merkle consistency proofs) and 3.5 (signed tree head): https://www.rfc-editor.org/rfc/rfc6962

4. SilentSpace audit trail: db/init/04-audit.sql (audit.log, audit.record(), audit.verify(), no-update and no-delete rules), run unchanged on 15 Oct 2026 in PGlite 0.5.8 (PostgreSQL 18.3). Results: 28 entries intact; UPDATE and DELETE with rules in place changed nothing; rules dropped, entry 5 edited named at 5, entry 5 deleted named at 6; last 3 entries deleted, intact at 25; entry 5 edited and every later hash recomputed, intact at 28. Last fingerprint before 4bcb7e5bd9b0, after cut 49fd7e4fa69b, after rewrite bd781e882bf4. A new entry written after a tail cut verified intact with ids jumping from 12 to 15. Source: SilentSpace, db/init/04-audit.sql.

5. SilentSpace evaluation report records the last entry id and hash: SilentSpace, lib/evidence.mjs (auditChain) and evaluate.mjs. Control mapping corrected from 2-11-P-1-5 to 2-11-P-1-4 on 15 Oct 2026 in SilentSpace lib/controls.mjs and the 04-audit.sql header comment.

6. SilentSpace product page, read 15 Oct 2026, sentence "any forced alteration is detectable": https://silentkeytechnologies.com/products/silentspace

7. NOAI disclosure ledger: src/ledger.ts (append, verifyLedger, signersOf) on main at commit 2468be0 (14 Oct 2026), https://github.com/SilentKeyTech/noai/blob/main/src/ledger.ts . Run 15 Oct 2026 with six made-up signed receipts: middle edit named at entry 2, middle deletion named at entry 2, last two cut from both files reported valid at 4, chain rebuilt without entry 2 from the remaining signed receipts reported valid at 5 with no signing key used.

8. BurnKey destruction log: BurnKey, src/chain.ts (appendToChain, verifyChain) BurnKey core at commit fa3306f (11 Oct 2026). Run 15 Oct 2026 with six made-up entries: last two cut reported valid at 4; entry 2 deleted named at entry 2.


Also published on LinkedIn on 15 October 2026: An audit log needs a witness

All essays Reply to this