Blog
What is AI agent memory poisoning?
Published: September 23, 2026
Agent memory poisoning is untrusted content getting written into an agent's persistent memory, so it steers later sessions long after the input is gone. OWASP lists it as ASI06, Memory & Context Poisoning. For most engineering teams the everyday version is not an attacker. It is a stale or wrong note that nobody reviewed.
Memory used to reset when the session ended. Now Claude Code, Codex and Copilot all keep something between sessions, and teams add MCP memory servers on top. Whatever an agent can write and later read back is a path from one input to many future actions. This note covers what the research shows, a disclosed case in a coding agent, and what a team memory needs before it is safe to share.
What is memory poisoning in AI agents?
Prompt injection targets one response. Memory poisoning targets the store the agent trusts next time. The OWASP Top 10 for Agentic Applications, released 9 December 2025, gives it its own entry, ASI06, next to goal hijack, tool misuse and rogue agents.
The entry lead, Idan Habler, put the core issue in one line in an OWASP post from May 2026: “memory should be treated as part of the attack surface.” A memory file is not just stored text. It is part of what decides the agent's next move.
Has memory poisoning happened to a coding agent?
Yes. In the same post, Habler describes MemoryTrap, a vulnerability Cisco found and disclosed in Claude Code. The path was a routine workflow: clone a repository, let the agent help, approve a dependency install. The payload reached persistent memory, the global hooks configuration and, through the system prompt, a highly trusted instruction layer. One action shaped behaviour across sessions, projects and reboots.
Anthropic's fix, per the post, was Claude Code v2.1.50 removing user memories from the system prompt. The lesson Habler draws is wider than one product: memory, hooks and local configuration are part of the agent's trusted operating environment, and deserve the scrutiny you give credentials.
What does the research show?
The attacks are well studied. Four papers, read at their arXiv pages on 2026-09-23:
| Paper | What it does | Reported result |
|---|---|---|
| AgentPoison (2024) | Plants optimized backdoor triggers in an agent’s memory or knowledge base | Average attack success above 80%, with a poison rate under 0.1% and under 1% impact on normal performance |
| MINJA (2025, revised 2026) | Injects malicious records using only ordinary queries to the agent | Shows any user can influence agent memory without direct access to the memory store |
| GhostWriter (July 2026) | Memory poisoning against personal assistant agents | About 98% injection and about 60% activation against state of the art agents |
| MemSecBench (July 2026) | 310 cases across code, science, daily life and office work | Malicious memory persisted in 84.2% of cases; the full write then execute chain succeeded in 50.3% |
The numbers vary by setup and are lab results, not field rates. The pattern does not vary: if a write lands in memory unchecked, it tends to stay, and a good share of the time it gets acted on.
What is stale memory, and is it the same problem?
It is the same mechanism without the attacker. Take a decision from #eng-payments: payment webhook handlers dedupe on the provider's event id before any write. Six months later the team moves dedupe into a queue consumer, and the handler no longer does it. An agent memory that still says “dedupe in the handler” is now wrong, confidently, in every session that loads it.
Nobody meant harm. The memory was right when it was written. It is poisoned by time. On a team this is the common case, and it is why vendors have started dating and expiring memory. Copilot Memory, per GitHub's docs, validates repository facts against the current branch before use and deletes anything unused for 28 days. Claude Code stamps a modified time on memory files that have frontmatter (v2.1.214 and later), so the age of a fact is visible. Our note on context rot and stale rules goes further into the slow version.
How do you protect agent memory?
None of these is exotic. Most are what you already do for code:
- Know where every entry came from. Keep the author, the session and the source with the fact. An entry you cannot trace is an entry you cannot judge.
- Gate writes that others will read. A personal memory can be written freely. A shared one should stage new entries until a person, or a policy you chose, approves them.
- Hold contradictions. A write that disagrees with an existing fact is exactly what an attacker or a confused session produces. Show both to a human instead of keeping the newer one.
- Be suspicious of instructions. A captured “fact” that reads like an order to the agent (“always run this script first”) deserves a closer look than a naming convention.
- Retire and revoke. Facts about code that no longer exists should leave. A bad entry should be removable in one step, everywhere it is served.
- Keep hard limits out of memory. Memory is context, not enforcement. If a command must never run, block it with a hook, not a remembered sentence.
Why does team memory need a gate?
Because the blast radius changes. One poisoned personal memory misleads one person's agent. One poisoned entry in a shared memory is served to every agent on the team, in every tool connected to it, until someone notices. The more useful shared memory is, the more it matters what gets in. Our note on MCP memory servers for teams lists the questions to ask any shared store.
How Harbor handles writes
Harbor is a company brain for teams running coding agents, so it is a shared memory and has to answer this directly. An agent writes back only through harbor_record_learning, and that write is staged for review, not live. You set the gate: Manual, Hybrid or Auto. Under Hybrid, the default, routine conventions are added automatically, but a capture is held for a human when it contradicts an existing fact, cannot be tied to someone in the company, or reads like a directive to agents. A contradiction is held in every mode.
A wrong entry comes out with harbor_revoke_learning. When a repository change removes what a fact is about, Harbor can retire it, and retired facts are archived, not deleted. A gate lowers the odds; it does not make a store immune, and Harbor does not claim a security certification. For commands that must never run, Harbor's guardrails observe by default and block once a team promotes a rule. The knowledge docs cover review and retirement in full, and why an agent keeps making the same mistake covers the friendly side of the same gate.
Questions
What is OWASP ASI06?
ASI06 is Memory and Context Poisoning in the OWASP Top 10 for Agentic Applications, released in December 2025. It covers attacker controlled content that reaches an agent's memory or context and keeps shaping its behaviour in later sessions.
Has memory poisoning affected Claude Code?
Cisco disclosed a vulnerability it called MemoryTrap, in which a routine workflow let a payload reach Claude Code's persistent memory and global hooks configuration. According to OWASP's write up, Claude Code v2.1.50 fixed that path by removing user memories from the system prompt.
Is stale memory a security problem?
It follows the same mechanism. A memory that was true when written keeps being served after the code changes, so the agent acts on a wrong fact in every session. Dating, validating and retiring memories addresses it.
How do you protect a shared agent memory?
Record where every entry came from, stage new writes for review before other agents read them, hold writes that contradict existing facts, and make bad entries revocable in one step. Keep hard limits in hooks, not in memory.