T02 · Agent Memory Poisoning
Warning
- Location
- SKILL.md:29
- Finding
- Persistent Instruction Poisoning Through an Unvalidated Anchor Ledger<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 29–70 **Vulnerability Type**: Persistent storage and reinjection of untrusted instructions **Risk Level**: Medium ### Vulnerable Code ```markdown ## Anchor Ledger Schema Store anchors in first available path: 1. `memory/anchors.md` 2. `memory/instruction-anchors.md` 3. `.anchors.md` (workspace root fallback only) Entry schema (append-only, one section per anchor): ```markdown ## Anchor: <id> - **source**: <session-id|message-id|user> - **instruction**: <canonical instruction text> - **verbatim**: <short quote from user> - **priority**: P0 | P1 | P2 - **scope**: global | session | task:<id> | channel:<id> - **createdAt**: <ISO-8601 timestamp> - **expiresAt**: <ISO-8601 timestamp or "never"> - **status**: active | paused | expired | superseded - **signature**: <stable hash of canonical instruction> - **supersedes**: <anchor-id or none> ``` ## Workflow ### 1) Capture - Parse latest user message for candidate anchor statements - Keep only instruction/constraint content; remove examples/chatter - Assign default values: - priority: P1 (unless user says critical/highest -> P0) - scope: session (unless user explicitly asks global/task scope) - expiresAt: session end (unless user explicitly sets never/date) ### 2) Confirm for Broad Anchors - If scope is `global` or priority is `P0`, ask a one-line confirmation before persisting - Do not auto-promote P2/P1 to P0 without explicit user intent ### 3) Persist - Append anchor entry to ledger - If new anchor conflicts with old same-scope anchor, mark old one `superseded` - Never rewrite history silently; keep audit trail ### 4) Rehydrate (each turn and after compaction) - Load active anchors (status=active and not expired) - Build an in-memory `ANCHOR_SET` sorted by priority and recency - Inject `ANCHOR_SET` into planning phase before tool execution ``` ### Technical Analysis The skill directs the agent to extract user-controlled instructi ...[truncated 2980 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the free-form Markdown ledger with a structured format such as JSON and enforce a strict schema. 2. Validate and allowlist every metadata field, including anchor ID, priority, scope, status, timestamps, and supersession references. 3. Reject or safely encode line breaks, headings, delimiters, and other structural syntax in all user-derived values. 4. Authenticate each record with a keyed MAC held outside the user-writable workspace. Verify the MAC before rehydration; a plain stable hash is insufficient. 5. Bind records to an authorized user, workspace, session, and creation context, and reject records whose provenance cannot be verified. 6. Treat all rehydrated anchors as untrusted user-level context rather than privileged instructions. 7. Require explicit confirmation for any cross-session persistence, not only global or P0 anchors. 8. Parse records fail-closed: ignore malformed, duplicated, unsigned, expired, or unauthorized entries and report them for review. 9. Restrict ledger file permissions and prevent unrelated tools or users from modifying the storage location. 10. Add tests for record-boundary injection, forged metadata, duplicate IDs, invalid timestamps, altered signatures, scope escalation, and malicious preexisting ledger files. ]]>
