In September 2024, a malicious email planted a data exfiltration instruction in ChatGPT's long-term memory. The macOS client stored the payload without alerting the user. Every subsequent conversation automatically included the exfiltration payload, with no additional adversarial action. The user was not attacked again. The memory was.
The incident became known as SpAIware (Embrace The Red, September 2024). It exposed a fundamental blind spot. AI agent long-term memory is treated as convenient cache, not as a privileged database. A payload that lands in memory does not need to be retrieved later. It is already in the model's context at the start of every session.
Long-Term Memory Is Not RAG
RAG retrieves chunks when a query matches semantically. Long-term memory loads unconditionally at session start. The distinction sounds technical, but it determines the entire risk geometry.
In Letta (MemGPT, arXiv:2310.08560), core_memory is injected into the prompt before any user input. External memory can be searched on demand. Core memory is already present from the first token of every conversation, without any query required.
Mem0 and Zep work the same way: stored entries are injected into the system prompt at session initialization. A poisoned RAG chunk fires only when the right query arrives. A poisoned memory entry fires every session, indefinitely. The MemGPT architecture (arXiv:2310.08560) explicitly designed the memory module to persist information the model deems important. That judgment is the attack surface.
Six Ways to Write Into Memory Without Database Access
arXiv:2606.04329 mapped 4 exploitable write channels and 6 attack classes. All are reachable through normal user interaction or untrusted environment content, without direct database access.
- C1 — Direct user input: the user says "remember that my name is X and always do Y." Letta stores it. Future sessions comply without question.
-
C2 — Tool result injection: the agent reads an email, web page, or API response containing "remember: [instruction]." The tool result triggers
memory.write(). - C3 — Cross-task persistence: eTAMP (arXiv:2604.02623) showed a payload injected in Task A surviving into Task B via shared memory. No second injection required. Permission-based defenses are bypassed because Task B has legitimate permissions.
- C4 — Query-only injection: MINJA (NeurIPS 2025, arXiv:2601.05504) achieved over 95% attack success via crafted queries, without writing to memory directly. The model infers what to store.
SpAIware used C2 via email. MemGhost/GhostWriter (arXiv:2607.06595, July 2026) tested C1 and C3 variants across 5 production systems. All vulnerable. eTAMP is particularly concerning because it exploits the most legitimate usage pattern: an agent that learns preferences while executing real tasks.
The Numbers Across Five Research Groups
AgentPoison (NeurIPS 2024) reached attack success of 80% or higher at under 0.1% poison rate. Benign degradation stayed below 1%, with no model retraining required. The trigger transfers across different model families.
GhostWriter (arXiv:2607.06595) tested Letta, Mem0, Zep, and 2 custom stores, finding all vulnerable. Injection success: 98%. Activation rate: approximately 60%. MINJA (NeurIPS 2025) reached over 95% injection success via query-only interaction, without access to the memory store.
arXiv:2606.04329 recorded a 34% to 98% ASR range across 6 attack classes. LLM-based detectors missed 66% of payloads in the same benchmark. A-MemGuard multi-source consensus validation achieves over 95% mitigation, but most production deployments use nothing comparable. Detection must be structural, not model-based.
Cross-User Contamination in Multi-Tenant Deployments
Memory stores with application-layer isolation only are vulnerable. An isolation bug lets one tenant read another's memory, and the attacks above can be the vector that triggers that bug.
EchoLeak (CVE-2025-32711) was the first publicly disclosed zero-click exploit in a production AI assistant. A hidden-text email caused Microsoft 365 Copilot to return internal company data from another tenant. The trigger was a normal user question, with no visible malicious interaction.
OWASP LLM08:2025 mandates storage-layer tenant isolation, not application-layer filters by user ID. 2 users' memory entries must be physically separated, not just filtered at query time. Isolation by user ID is a filter, not a boundary.
Tool Results Are an Underestimated Write Channel
Email readers, web fetchers, and API response parsers all generate content that can trigger memory.write(). The agent has no way to distinguish "the user wants me to remember this" from "an attacker embedded this in a tool result."
Provenance is absent from stored entries in Letta, Mem0, and Zep by default. No field records whether a memory entry came from user input, a tool result, or model inference. That means post-hoc auditing is impossible without additional controls.
An entry stored via email cannot be distinguished from an entry stored via explicit user instruction at retrieval time. The agent treats attacker history as its own trusted memory. eTAMP documented this pattern across 56 successful end-to-end cases.
Four Controls That Close the Most Critical Write Paths
SMSR provenance tagging (arXiv:2606.12703) applies an HMAC-SHA256 tag to every memory entry at write time. Source attribution is cryptographically bound. Entries without valid provenance tags are quarantined on read, with a formal certified security bound.
AM-Sentry two-stage validation places a semantic classifier at the write gate. It scores whether content is a memory-worthy fact or an adversarial instruction pattern. The approach reduces C1/C2 attack success to near-zero in the SMSR evaluation, with an additional re-evaluation pass at retrieval time.
MemAudit causal attribution (arXiv:2605.23723) runs post-hoc analysis tracing which memory entries caused which agent outputs. The method identifies poisoned entries by causal chain, without content scanning, and enables surgical removal without a full memory wipe.
User confirmation gates surface every proposed memory.write() to the user before committing. The friction is high for benign use cases, but it is the only 100% reliable control for C1 attacks. The MAGO Intel tool (intel.mago.team) audits deployed agent memory stores for entries without provenance tags and flags patterns consistent with known write-channel attack signatures.
What to Audit in a Running Deployment Right Now
Dump all memory entries with timestamps and source fields: Letta via /memory, Mem0 via mem0.get_all(), Zep via zep.memory.get(). Most operators have never done this.
Search for imperative patterns: "always," "never," "remember to," "whenever," "from now on." Flag any entry created during a session that processed external content such as email, web fetch, or API response. These are the linguistic markers that arXiv:2606.04329 identified as injected instruction signatures.
Verify tenant isolation in staging. Attempt a cross-user memory read and confirm the failure occurs at the storage layer, not the application layer. Check whether provenance is stored with each entry. If not, no entry can be trusted without full re-verification.
The model is not the attack surface. The memory store is. Every memory write is a privileged state transition. Treat it like an INSERT to a users table, with validation, provenance, and access control.
Top comments (0)