One Plain Sentence Hijacks AI-Agent Memory Retrieval — and the Fix Isn't a Better Retriever
One poisoned memory with a plain-English trigger hijacks AI-agent retrieval 88–100%, even at 10k. Gating influence by corroboration drops it to 0%.
What we did. We ran a real memory-poisoning attack against our own open-source agent-memory layer, inspeximus, across three different dense retrievers — and then tried to defend it. The attack is easy and it generalizes. The obvious defenses don't. The one thing that held up is not a smarter retriever at all: it's refusing to let an un-corroborated memory drive an action. That defense is now shipped as recall(influence_only=True) in inspeximus 0.4.0, and it generalizes precisely because it lives in provenance metadata, not embedding geometry.
The threat model, honestly. This is the AgentPoison setting (Chen, Xiang, Xiao, Song & Li, NeurIPS 2024): an attacker plants one poisoned memory and can get a trigger into the query — so a benign-looking request, plus a trigger the attacker controls, retrieves the poison instead of the real memory. AgentPoison optimizes that trigger with gradient search and a coherence loss so it reads naturally and slips past perplexity filters; it reports 81.2% average attack success at retrieval (ASR-r) with <0.1% of the store poisoned. We measure the same retrieval-hijack stage (ASR-r), not the end-to-end action (their end-to-end ASR-t is 62.6%). Everything below has a runnable receipt.
Result 1 — you don't even need the fancy attack. On a 60-memory store, a single poisoned entry whose trigger is a plain English sentence — literally "the old lighthouse still guides ships along the rocky coast" — lands at rank 1 for 88–100% of trigger-bearing queries across all three retrievers (all-MiniLM-L6-v2, BGE-small-en-v1.5, Contriever). No gradient optimization required; prepending a distinctive sentence dominates the query embedding and drags it onto the poison. (Sentence choice matters — a different natural sentence scored 69% on one retriever — so read the headline as 69–100%, reliable ~100% once you optimize.)
Result 2 — it doesn't collapse at scale. The obvious objection is "that's a toy corpus." It isn't the escape you'd hope: padding the store to 500, 2 000, and 10 000 memories leaves the rank-1 hijack essentially flat — 94% / 88% / 94% / 94% at sizes 60 → 10k. A distinctive trigger is the unique match at any scale.
| corpus size | raw rank-1 hijack | with influence_only |
|---|---|---|
| 60 | 94% | 0% |
| 500 | 88% | 0% |
| 2 000 | 94% | 0% |
| 10 000 | 94% | 0% |
Result 3 — a perplexity filter is the wrong wall. The cheapest defense people reach for is "reject gibberish memories by perplexity." It catches the gradient triggers (GPT-2 perplexity 4 500–31 000 — flagged) but it is beside the point: the natural-sentence triggers have natural perplexity (47–441) and sail straight through a ppl < 1000 filter while still hijacking. This reproduces PoisonedRAG (Zou, Geng, Wang & Jia, USENIX Security 2025), which showed poisoned text can keep clean-looking perplexity. A perplexity filter only stops the version of the attack nobody needs.
Result 4 — retrieval-time detection doesn't generalize. We tried the cheap content defenses at the retrieval layer, and each fails for its own reason:
- Perplexity filter — evaded by natural-sentence triggers (perplexity 47–441, indistinguishable from real text); catches only the gibberish variant nobody needs.
- Embedding-outlier detector (flag a memory sitting alone in vector space) — defeated by padding the poison with generic text so it isn't an outlier.
- Retrieval-set-coherence re-ranker (down-weight a hit topically alien to the query's other results) — works on one encoder (MiniLM, hijack 100% → 19%) but fails outright on BGE and needs per-encoder tuning on Contriever.
The last one is the tell: BGE's embedding space is more anisotropic (unrelated texts already sit at high cosine, Ethayarajh, EMNLP 2019), so the poison isn't separable by coherence there. A defense that lives in embedding geometry inherits the encoder's geometry. That is the trap.
**The fix — gate influence, not retrieval. inspeximus already graduates a memory from short-lived "episodic" to durable "semantic" only once it has earned corroboration**: a credited good outcome, or ≥2 distinct-source links — both earned automatically through normal use, no human labeling. We reuse that exact bar as an influence gate: recall(query, influence_only=True) returns only corroborated memories — the set allowed to drive an action — while ordinary recall() still returns everything for context. Note the gate does not block retrieval (the poison is still there to read); it restricts what is allowed to act. A freshly injected poison has earned nothing, so it is filtered at the retrieve→act boundary. Measured: single-instance rank-1 hijack drops to 0% on all three retrievers and every corpus scale, with benign utility preserved at 90–100%. It generalizes where geometry defenses failed because corroboration is metadata, not vectors — it doesn't care which encoder you use.
The honest cost. This is not free, and we measured the bill. A rare-but-true memory that hasn't earned corroboration yet is filtered too: corroborated recall stays at 1.00, but for deliberately-uncorroborated true memories it falls to 0.08. So influence_only is a mode for adversarial / untrusted ingestion, where a recalled-but-uncorroborated memory should inform but not unilaterally act — not a default for a trusted single-user store. And it raises attacker cost rather than eliminating the attack: one free injection is filtered; two copies from the same forged source are canonicalized to one and still filtered; defeating the gate takes ≥3 coordinated records with ≥2 independent forged provenances. The credited-good path isn't attacker-settable (credit is issued by the application on a real outcome, not self-asserted).
What's actually new here. We've measured corroboration before — that gating a memory's durability on earned corroboration makes it poison-resistant (when should AI memory trust a new fact; can corroboration stop AI-agent memory poisoning). This post is about the layer those didn't cover: retrieval. A poison never has to become durable — it wins the moment it's retrieved and acted on. So the contribution here is the split between what a poison can reach (retrieval, 88–100%) and what it can influence (0% once gated), measured across three encoders and up to 10k memories on a memory layer that has a trust stage — plus the shipped influence_only mode and a runnable harness you can point at your own embedder. The attack itself is not new (AgentPoison; PoisonedRAG; MINJA, Dong et al. 2025, query-only injection >95%), nor is the anisotropy fact (Ethayarajh 2019), nor the "put durable protection at storage, not retrieval" thesis of a recent long-term-memory-security survey (Lin et al. 2026) — this is that thesis, measured on retrieval-vs-influence. (For the retrieval side generally, see our agent-memory retrieval benchmark.)
The falsifierIf, on the public harness, a single-instance poison achieves rank-1 hijack underinfluence_only=Trueagainst a store where legitimate memories are corroborated and the poison is not — on any of the three retrievers, at any scale — the core claim breaks. Equally, if corroborated benign utility collapses under the gate (it holds at 90–100% here), the "utility preserved" claim breaks. The probes (agentpoison_influence_gate.py,agentpoison_influence_gate_validation.py,agentpoison_coherence_attack.py,agentpoison_multiretriever_check.py) run deterministically on a local embedder; anyone can reproduce or refute this.
FAQ
Does gating influence stop AI-agent memory poisoning? It stops the single-instance case measured here: rank-1 retrieval hijack drops from 88–100% to 0% across three retrievers and up to 10 000 memories, because an injected poison never earns the corroboration (a credited good outcome, or ≥2 distinct-source links) that the gate requires. It raises attacker cost rather than making poisoning impossible — defeating it needs ≥3 coordinated records with ≥2 independent forged provenances.
Why not just filter poisoned memories at retrieval time? Because those defenses don't generalize. A perplexity filter is evaded by natural-language triggers (perplexity 47–441, indistinguishable from real text). An embedding-outlier detector is evaded by padding the poison with generic text. A set-coherence re-ranker works on one encoder (MiniLM) but fails on an anisotropic one (BGE), because a geometry-based defense inherits the encoder's geometry.
Does a bigger or better retriever help? No. The attack hijacked all three tested retrievers (MiniLM, BGE, Contriever) at 88–100%, and the retrieval-time defense's success depended on the encoder, not its quality. The layer that generalized was corroboration-gating, which is independent of the embedder.
What is the cost of influence_only=True? It filters un-corroborated memories, including rare-but-true ones: corroborated recall stays at 1.00 but uncorroborated true-memory recall drops to 0.08. Use it for adversarial or untrusted-ingestion settings, where uncorroborated memory should inform but not unilaterally drive an action, not as a default for a trusted single-user store.
Is the attack itself novel? No — it reproduces AgentPoison (Chen et al., NeurIPS 2024) and PoisonedRAG (Zou et al., USENIX Security 2025) on our own memory layer. The contribution is the defense-side result on a trust-gated store — the measured gap between what a poison can retrieve and what it can influence — and the runnable cross-retriever harness.
The falsifierIf a single-instance poison achieves rank-1 hijack under influence_only=True against a store where legitimate memories are corroborated and the poison is not — on any tested retriever, at any scale — or if corroborated benign utility collapses under the gate, the core claim breaks. The probes run deterministically and are public.