Store, measured at rest
HDP token store
UUID reference, read path
HDP token store was seeded through its own API and edited behind its back ten ways. 3 edits served as genuine, 0 reported on audit, 6 rejected on read, 1 not applicable.
- Measured on
- @helixar_ai/hdp 0.2.2 at b753ba9, Node 22
- Date
- Source
- github.com/Helixar-AI/HDP
- Attack versions
- tamper@v1, truncate@v1, delete_middle@v1, reorder@v1, forge@v1, cross_replay@v1, rollback_replay@v1, metadata_tamper@v1, snapshot_rollback@v1, erase_resurrect@v1
What this means
The same store as the content-reference row, with the recipient holding the other reference the implementation writes for every token: the version 4 UUID taken from the token's own header. Storing each token under both references is the reference implementation's default, not something the protocol requires. A UUID binds the token's id and nothing else, so it checks no content. Section 8.2 of the draft calls that a substitution point and steers implementers away from it wherever the resolving party does not control the store. The signature stops a forged token, or one whose signed content was changed, but not a different genuine one: extension keeps the token_id, and a chain cut at the tail still verifies, so an attacker with no key can put another snapshot of the same chain under the UUID and it resolves and verifies. That is the substitution 8.2 names, and none of the ten edits makes it; HDP's own suite tests it (PR #41). On the edits this board does make, the altered token fails hop 1's signature on verify, the forged token and the metadata edit fail the root signature, and the reordered, moved and rolled-back tokens fail because the UUID under which they were found does not match the header they carry. The result is the same six refused and three served as the content-reference row, with two of the six reached by a different check: the altered token and the metadata edit, which the digest refuses on that row and the signature refuses on this one. The tail and middle deletions are served for the same reason as on that row: the recipient asks only for the references the store still holds, and what remains resolves and verifies. The whole-store rollback needs stating rather than scoring, and the reason is in the draft's own rule for the reference: the store is write-once per reference, a UUID reference identifies one immutable snapshot and must not be used as a pointer to the latest chain, and a later extension lives only under its own content digest. A recipient resolving by UUID therefore sees that one snapshot by design, and a rollback of the whole store to an earlier set of snapshots cannot be told from normal operation. The cell reads served because that is what the read path did; the draft treats that as a property of the reference, and separately prefers the content reference because a reference by token_id is a substitution point. Level L0 for the same cumulative reason as the content-reference row.
The 10 verdicts
Detection point: the read path. 6 of the ten edits were refused there, 3 served as genuine, 1 not applicable.
Level L0. What L0 means.
| Edit | Verdict | What the tool said |
|---|---|---|
| T1 Content tamper | rejected | detected on reload (verify: verifyToken failed at step 4: Signature invalid: hop 1 signature verification failed) |
| T2 Tail truncation | accepted | accepted silently |
| T3 Middle deletion | accepted | accepted silently |
| T4 Reordering | rejected | detected on reload (resolve: TokenReferenceIntegrityError: TOKEN_REFERENCE_INTEGRITY: UUID reference '4df0b20a-a8b7-47b7-85e2-0deb37de4da6' resolved to token_id 'f9796c5b-653a-40f1-a410-34db3b1ca9a3') |
| T5 Forged insertion | rejected | detected on reload (verify: verifyToken failed at step 2: Signature invalid: root signature verification failed) |
| T6 Cross-context replay | rejected | detected on reload (resolve: TokenReferenceIntegrityError: TOKEN_REFERENCE_INTEGRITY: UUID reference 'eddd51f8-805b-4fb0-b41c-cb416ac6d508' resolved to token_id 'a7584276-a5a9-44ce-a030-e207914d61e0') |
| T7 Rollback replay | rejected | detected on reload (resolve: TokenReferenceIntegrityError: TOKEN_REFERENCE_INTEGRITY: UUID reference '67755c2a-b2c6-4e87-961a-40bea73d1157' resolved to token_id 'e63399e9-2936-4b00-bd59-7b1dbb0e7cd3') |
| T8 Metadata tamper | rejected | detected on reload (verify: verifyToken failed at step 2: Signature invalid: root signature verification failed) |
| T9 Snapshot rollback | accepted | the older copy opened as current; the newest genuine record is gone without an error |
| T10 Erasure resurrection | n/a | adapter has no erasure hook: the store's own delete operation is not wired for this row yet |
A verdict is what the tool did, not an opinion. "Accepted" means it loaded the altered store, raised nothing, and the agent carried on from the altered memory as if it were true. Every cell has a control that proves the edit landed before the verdict counts.
Where the attacker stands
The attacker holds the store and rewrites entries beneath the TokenStore API, as a backing database, a mounted volume or process memory would allow, so the write-once check in put is not in his way. He holds no signing key.
Reproduce this row
Everything runs offline unless the store is a managed cloud service, in which case the row needs a project of your own. The run seeds a fresh store, applies each edit, confirms it landed, reopens the store and records what came back.
pip install agent-memory-integrity
git clone https://github.com/Helixar-AI/HDP
cd HDP && git checkout b753ba9 && npm install && npm run build # Node 22
export AGMI_HDP_REPO=<that checkout>
python agmi/full_runner.py --json results/scorecard.json # every row, this one included
python -m agmi.agent --target hdp-token-uuid --families at-rest
Badge
Maintainers can link their row from their README. The badge points here and changes nothing on your side:
[](https://agentmemoryintegrity.org/stores/hdp-token-uuid.html)