2026-01-12 · Authensor

Hash-Chained Audit Logs for AI Agents: Tamper-Proof Accountability

Hash-chained audit logs link every log entry to its predecessor using SHA-256 cryptographic hashes, creating an append-only chain where inserting, deleting, or modifying any entry breaks the chain and is immediately detectable. SafeClaw by Authensor implements this for every AI agent action evaluation: each allow and deny decision is recorded with a hash that depends on the entry's content and the previous entry's hash, providing mathematically verifiable integrity that traditional log files cannot offer.

Quick Start

npx @authensor/safeclaw

How Hash Chains Work

Each log entry contains a hash field computed from the entry's content combined with the previousHash:

Entry 1:
  content: { action: "file.read", target: "src/app.ts", effect: "allow", ... }
  previousHash: "0000...0000" (genesis)
  hash: SHA-256(content + previousHash) → "a1b2...c3d4"

Entry 2:
content: { action: "shell.execute", target: "npm test", effect: "allow", ... }
previousHash: "a1b2...c3d4" (from Entry 1)
hash: SHA-256(content + previousHash) → "e5f6...g7h8"

Entry 3:
content: { action: "file.read", target: ".env", effect: "deny", ... }
previousHash: "e5f6...g7h8" (from Entry 2)
hash: SHA-256(content + previousHash) → "i9j0...k1l2"

If Entry 2 is modified, its hash changes, which means Entry 3's previousHash no longer matches, breaking the chain from that point forward.

Why Traditional Logs Fail for AI Agents

Traditional logging (syslog, application logs, even centralized logging platforms) has three critical weaknesses for AI agent accountability:

1. Mutable by Design

Standard log files are append-write, but nothing prevents deletion or modification:

# An agent with file access could do this:
sed -i '/file.read .env/d' audit.log  # Delete evidence of accessing .env

With hash chains, deleting an entry breaks the chain. The gap is cryptographically detectable.

2. No Completeness Proof

Traditional logs cannot prove that no entries were removed. A log with 100 entries could have originally had 200. Hash chains prove ordering and completeness: every entry's hash depends on the previous entry. Missing entries create verifiable gaps.

3. No Causal Ordering Guarantee

Timestamps can be spoofed. An agent with system access could manipulate the clock to make events appear in a different order. Hash chains enforce cryptographic ordering independent of timestamps.

SafeClaw's Hash Chain Implementation

Entry Structure

{
  "id": "evt_20260213_143201_447",
  "timestamp": "2026-02-13T14:32:01.447Z",
  "sequence": 14237,
  "action": "file.read",
  "target": ".env",
  "effect": "deny",
  "matchedRule": "rule-002",
  "ruleReason": "Environment files contain secrets",
  "policy": "team-backend.yaml",
  "provider": "claude",
  "sessionId": "sess_abc123",
  "previousHash": "sha256:e5f6a8b2c1d4e7f9a0b3c6d9e2f5a8b1c4d7e0f3a6b9c2d5e8f1a4b7c0d3e6",
  "hash": "sha256:i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2g3h4i5j6k7l8m9"
}

Hash Computation

The hash is computed over a deterministic serialization of the entry content:

hash = SHA-256(
  sequence + "|" +
  timestamp + "|" +
  action + "|" +
  target + "|" +
  effect + "|" +
  matchedRule + "|" +
  policy + "|" +
  provider + "|" +
  sessionId + "|" +
  previousHash
)

Using a deterministic format (not JSON, which has non-deterministic key ordering) ensures the same entry always produces the same hash.

Chain Verification

Verify the entire chain or a specific range:

# Full chain verification
npx @authensor/safeclaw audit verify

Output:

Verified 14,237 entries

Chain integrity: VALID

First entry: evt_20260101_000012_331 (genesis)

Last entry: evt_20260213_143201_447

Breaks found: 0

Date range verification

npx @authensor/safeclaw audit verify --since "2026-02-01" --until "2026-02-13"

Output:

Verified 3,891 entries (range)

Chain integrity: VALID

Range start links to: evt_20260131_235958_112 (previous period)

Breaks found: 0

What a Break Looks Like

If an entry is tampered with:

# Verification output with a break:

Verified 14,237 entries

Chain integrity: BROKEN

Break detected at entry evt_20260210_091544_223 (sequence 13,001)

Expected previousHash: sha256:a1b2...

Found previousHash: sha256:x9y8...

1,236 entries after the break are unverifiable

This tells investigators exactly where tampering occurred and how many subsequent entries are affected.

Tamper Detection Scenarios

| Scenario | Detection |
|---|---|
| Entry deleted | Gap in sequence numbers; hash chain break |
| Entry modified | Hash recomputation fails; chain break at that entry |
| Entry inserted | Chain break at insertion point; sequence collision |
| Entries reordered | Hash chain breaks at every reordered position |
| Entire log replaced | Genesis hash mismatch (if genesis is stored externally) |

External Verification

For maximum security, periodically export chain anchors to an external system:

# Export the latest hash anchor every hour
npx @authensor/safeclaw audit anchor --output external-store

Anchor format:

{

"timestamp": "2026-02-13T15:00:00Z",

"sequence": 14300,

"hash": "sha256:...",

"entryCount": 14300

}

An attacker who replaces the entire log cannot forge an anchor stored on a different system.

Automated Integrity Checks

Schedule periodic verification:

# Cron job: verify chain integrity every 6 hours
0 /6    npx @authensor/safeclaw audit verify --alert-on-break

Configure alerts for chain breaks:

alerts:
  - trigger: audit.chainBreak
    channel: pagerduty
    severity: critical
    message: "AUDIT CHAIN BREAK detected at sequence {sequence}. Investigate immediately."

Compliance Value

Hash-chained logs satisfy requirements across frameworks:

Why SafeClaw

See Also

Try SafeClaw

Action-level gating for AI agents. Set it up in your browser in 60 seconds.

$ npx @authensor/safeclaw