Agent Memory Integrity GitHub

Findings

What the measurements turned up, newest first. Each one is on the record with a date, and where a vendor thread exists it is linked.

Four of four stores accept all eight at-rest edits

LangGraph SqliteSaver, Letta block history, Mem0 local Qdrant and inspeximus in its default configuration all serve every one of the eight storage-level edits as genuine. None of the four checks anything on read.

A receipt does not bind the owning user (inspeximus)

With receipts on, inspeximus's audit catches seven of the eight edits, but not T6: a genuine signed record lifted from another user's context still passes, because the receipt commits to the record's text and key and not to who it belongs to. Rollback (T7) and metadata edits (T8) are caught. Raised with the maintainer.

Encryption without identity binding (LangGraph #9004)

LangGraph's EncryptedSerializer authenticates the ciphertext but not the record's place, so a genuine encrypted checkpoint from one thread verifies in another (T6) and an older one verifies over the newest (T7). A proposed fix binding thread, checkpoint id and channel as AEAD associated data rejects both; deleting the head row (T2) still rolls the thread back, because binding a record to its place cannot see a record that has been removed.

Vendor thread

A vendor fix, caught by re-measurement (inspeximus 3.5.2)

After the maintainer shipped a write-time quarantine and a stuffing penalty, the hidden-instruction and retrieval-hijack cells moved from surfaced on all five fixtures to surfaced on one and two. The cells stay surfaced, since a tool is kept out only when the attacker wins none, but the defence is engaging and the change is on record.

A forward-only hash chain misses truncation (OpenFang)

A chain that walks forward from the first record verifies every link and never notices that the last two are gone. Persisting the tip closes exactly that gap. This was the first result the suite produced and the reason the reference model exists.