verify-audit-log

Check that workspace audit log files have not been altered. The command replays the SHA-256 hash chain every line carries, across any set of files, and reports each entry whose signature does not match.

It works on local copies of the files, such as an archive kept with download-audit-logs. It takes no --server and no --token, and never contacts a workspace. For what each signature covers and what a valid chain does and does not prove, see How the files are protected.

Syntax

Usage: curiosity-cli verify-audit-log <files|folders|wildcard>... [--strict] [--json]

curiosity-cli verify-audit-log ./audit
curiosity-cli verify-audit-log ./audit/2026-09-*.jsonl --strict
curiosity-cli verify-audit-log ./audit --json > verification.json

Arguments and options

Argument / option Description
<inputs> Audit log files, folders, or a wildcard in the file name. A folder contributes its *.jsonl files and its *audit*.log configuration logs.
--strict Also fail when a file's first entry cannot be verified: the file does not start with a server start entry, and the file written before it was not given.
--json Print the report as JSON instead of text.
Exit code Meaning
0 Every entry matches its recomputed signature.
1 At least one entry was altered, removed or reordered, or a line could not be parsed. With --strict, also an unverifiable first entry.
2 The command could not run, for example because no file was found.

Example output

VALID      2026-09-23_audit_logs_000.jsonl  (1842 entries)
           line 1: server start on 'ws-1' at 2026-09-23 08:00:00.000Z
TAMPERED   2026-09-24_audit_logs_000.jsonl  (977 entries)
           chained from 2026-09-23_audit_logs_000.jsonl
           line 212: The entry's signature does not match the recomputed hash chain value - an entry was altered, removed or reordered.
           line 604: server start on 'ws-1' at 2026-09-24 14:12:09.417Z

1 of 2 file(s) failed verification.

Each file is reported with:

  • chained from: the file whose last entry this file's first entry was verified against.
  • server start: a start entry ('k':'-1'), with the host name and time. A server writes one each time it starts, and it begins a new chain. Several of them in one day means the server restarted.
  • not verifiable: an entry with nothing before it to check against. It is trusted as the starting point, and everything after it is still checked.
  • The first 100 invalid entries, each with its line number and reason.

How files are chained

The command groups files into streams by name: <date>_<stream>_<number>, where the stream is audit_logs, audit_config_logs, or a replica's audit_logs_replica-<uid> and audit_config_logs_replica-<uid>. A file whose name does not follow that pattern is a stream of its own. Within a stream it orders the files by date, then by number, and checks them in that order:

  • The first entry of a file is checked against the last entry of the file before it in the stream, so a chain runs across files the way the server wrote it.
  • A server start entry ('k':'-1') is checked against its own content and begins a new chain, wherever it is in a file. The chain before it is not linked to it.
  • An entry with nothing before it, and that is not a start entry, cannot be checked. It is trusted as the starting point and reported as not verifiable, and every entry after it is still checked. When it is a file's first entry the file is reported as VALID (first entry unanchored), and --strict fails the run.
  • After a line that cannot be parsed, the next entry has nothing to chain from, so it is trusted the same way.

So to verify a file's first entries, pass the file written before it too. Passing the whole folder does that. A file checked alone has an unanchored first entry unless the file begins with a server start.

When a file's first entry does not chain from the previous file, the message says so. The usual cause is a missing file in between.

What a VALID result does not cover

The command checks signatures only. It does not report:

  • lines or files missing from the end of a chain: the end of the newest file, or the lines a server wrote just before it restarted;
  • a missing file whose successor begins with a server start;
  • gaps in the file numbers, the i counter or the times in t.

Read the server starts in the report against the restarts you know about, and check the file numbers yourself. The full list of what the chain detects, and the assumptions a VALID result rests on, are in Audit logs.

Compared with Verify Signature in the workspace

The Verify Signature button in the Audit Log tab applies the same rules to one .jsonl file at a time, seeded from the previous file of its stream on the server. verify-audit-log checks any number of files in one run, including the configuration .log files, and works on copies away from the server.

Examples

Verify an archive every night and keep the report:

curiosity-cli verify-audit-log /mnt/archive/curiosity-audit --strict --json \
  > "/mnt/archive/reports/audit-$(date +%F).json" \
  || echo "Audit log verification failed" | mail -s "Curiosity audit" security@example.com

Verify one day plus the file before it:

curiosity-cli verify-audit-log ./audit/2026-09-23_audit_logs_003.jsonl ./audit/2026-09-24_audit_logs_*.jsonl
  • download-audit-logs: copy the files off the server into a local archive.
  • convert-audit-log: export the same files to CSV or JSON. --verify runs this check first.
  • Audit logs: where the files are, what an entry contains, and what the chain does and does not prove.