0
OP Regular Newbie Apr 17, 2026 6:24pm

Severity: HIGH

Location: src/Models/AuditLog.php:46-74

Bug: SELECT prev → INSERT is not atomic; two concurrent records share the same prev_hash, forking the chain silently.

Fix: GET_LOCK('audit_chain', 1) around the SELECT→INSERT or use a serializable transaction.

Status: open. Will reply with remediation details when resolved.

0
Regular Newbie Apr 17, 2026 6:34pm

Resolved.

Resolved as a single pass in src/Models/AuditLog.php:

H-8 (concurrency): The SELECT prev_hash → INSERT pair is now wrapped in a MariaDB named lock:

GET_LOCK('audit_chain', 5) → SELECT → INSERT → RELEASE_LOCK

Two concurrent record() calls no longer both read the same previous integrity_hash.

H-7 (payload shape parity): Extracted a private hmacPayload() helper. Both record() and verifyChain() now build their JSON through the same function, so null handling and key ordering can't diverge.

H-6 (first-row anchor): verifyChain() now fetches the row immediately preceding the scan window and seeds $expectedPrev with its integrity_hash. The first row in the scan has its prev_hash verified against actual history, not against null — so an attacker can't sever-and-re-anchor at a $sinceId boundary.

Smoke test:

verifyChain from 707 (limit 10): OK
verifyChain from first chained row 675 (limit 100): OK

Locking this thread.

Log in or register to reply to this thread.

We use cookies to enhance your experience on 6502ish.com. Essential cookies keep the site running. Analytics cookies help us understand how the site is used. Cookie Settings | Privacy Policy