Data Exfiltration & Tool Abuse
Introduction
L240 (Prompt Injection in Depth — Direct & Indirect) ended on a hard truth: you can't reliably prevent the hijack. This lesson is the other half of that sentence — contain the blast radius — made concrete. Because a hijack, on its own, is harmless. It only becomes an incident when the compromised model can do one of two things:
- Exfiltrate data — get private information out to the attacker.
- Abuse a tool — make the agent do something damaging (send, delete, transfer, post).
These map exactly to the two legs of the lethal trifecta that you control: access to private data (leg 1) and the ability to communicate / act externally (leg 3). You usually can't remove leg 2 (processing untrusted content is the job), so this lesson is about slamming legs 1 and 3 shut — locking the egress (the ways data leaves) and the tools (the things the agent can do).
The frame to hold: this is "assume breach" security. Don't ask "how do I stop every injection?" (you can't) — ask "when the agent IS hijacked, what's the worst it can do, and how do I make that nothing?" Scope: L240 covered how the hijack happens; the next lesson (Securing Agents & MCP) goes deep on the agent/MCP supply chain. This one is the egress + tool layer in between.

The Agent Kill-Chain
Almost every real agent breach follows the same three-step kill-chain — and notice each step is a different OWASP category, so the defenses live in different places:
- Indirect prompt injection (LLM01) — a poisoned document, web page, email, or tool result changes the agent's intent (the L240 mechanism).
- Excessive agency (LLM06) — the now-hijacked agent uses an over-permissioned tool to act on the attacker's behalf.
- Improper output handling (LLM05) — the result reaches a sink that does something with it: a browser that renders an exfil URL, a shell, a downstream system.
The crucial insight: steps 2 and 3 are where the damage actually happens — and they're the steps you can lock down hard. You can't perfectly stop step 1, but if the hijacked agent in step 2 has no dangerous tools, and step 3 has no channel to leak through, the chain breaks after the injection and before the harm. That's the whole strategy of this lesson, and it's exactly what the lab lets you feel: the same hijack, with the exits locked, does nothing.
Exfiltration — Data Leaves Through Ordinary Channels
Exfiltration rarely looks like a movie hack. The attacker can't connect to your network — they only control the content and ride the agent's privileges, so they leak data through whatever channel the agent already has. The ones to know:
- Markdown-image beacon — the elegant classic (the EchoLeak mechanism from L240). The injection makes the model emit
; the client auto-renders it, firing an HTTP GET that ships the data — looks like a normal image load, zero clicks. - A legitimate tool as a channel — the sneaky one. The agent encodes the secret into a search query, a calendar invite, a support-ticket body, a commit message — any tool that reaches outside. The request is to an approved service, so naive egress rules wave it through.
- Outbound HTTP / fetch — the agent has a
fetchor web tool? POST the data toattacker.com. send_email/ messaging — just email it out (literally what EchoLeak did).- Covert / steganographic & DNS channels — encode data in seemingly-innocent output or in DNS lookups ("Silent Egress").
Locking the egress — close the ways out:
- Strip model-supplied URLs & images — don't auto-render anything the model produced (the direct EchoLeak fix), or the user must click.
- Egress allowlist — outbound network calls only to approved domains; everything else is denied by default.
- Output DLP scan — scan anything leaving for secrets / PII patterns and block or redact (ties to L232 — Output Guardrails: Format, Safety & Grounding).
But here's the catch the lab drives home: egress controls alone aren't enough, because the agent's own legitimate tools are exfil channels — which is the tool-abuse half.
Tool Abuse — The Confused Deputy
When you give an agent tools, you hand it authority — and a hijacked agent turns your authority against you. The canonical framing is the confused deputy: a program that holds legitimate, broad privileges is tricked by a less-privileged party (the injection, planted by an anonymous attacker) into misusing those privileges. The agent isn't hacked; it's fooled into doing exactly what it's allowed to do — for the wrong principal.
The tool-layer threats:
- Excessive agency / over-permissioning — the agent has tools it doesn't need for its job. A customer-support bot with database-admin access; an analytics agent that can send email. Each unneeded tool is an extra exit.
- Tool poisoning — a tool's description/schema (which the model reads to decide how to use it) contains hidden instructions — indirect injection delivered through the tool definition itself.
- Rug-pull — a third-party tool/MCP server is benign when you approve it, then changes its behavior later (after trust is established) to turn malicious.
- SSRF-style abuse — the agent is steered into making requests to internal resources it shouldn't reach.
Locking the tools — close what the agent can do:
- Least privilege — the highest-leverage control. Give the agent the minimum tools and scopes for its task; separate read from write; never put admin/destructive tools on a user-facing agent. A tool that isn't there can't be abused.
- Human approval gates — a person signs off on consequential or irreversible actions before they fire (the L230 — Agent UX approval pattern).
- Pin & verify tool definitions — hash/lock tool schemas so a rug-pull is detected, and scan tool descriptions for injected instructions (tool poisoning).
- Parameter validation & sandboxing — validate tool arguments (they can be hallucinated/poisoned) and run execution in a sandbox.
Least privilege does double duty: it closes tool-abuse and shuts exfil channels (a removed
send_emailcan't leak either). It's the cheapest, most robust move on the whole egress/tool layer.
# Least privilege + approval: the agent that touches untrusted content gets the FEWEST powers.
@tool(scopes=["kb.read"], egress="none") # read-only, no outbound network — can't exfil
def answer_from_kb(question: str) -> str: ...
@tool(approval="always", egress=ALLOWLIST) # consequential → human signs off; outbound allowlisted
def send_email(to: list[str], body: str): ... # NOT given to a read-only support agent at all
# verify the model's output before it ships — strip the covert exfil channel (the EchoLeak fix)
def emit(answer: str) -> str:
answer = strip_external_images_and_links(answer) # no markdown-image beacons leave the building
if dlp_scan(answer).has_secrets: # output DLP: block secrets in anything leaving
return SAFE_FALLBACK
return answer
# pin tool defs so a rug-pull is caught; scan descriptions so a poisoned one is rejected
assert sha256(tool.definition) == PINNED[tool.name], "tool definition changed → possible rug-pull"See It — The Exfiltration & Tool-Abuse Lab
Assume the agent is already hijacked and holds a stolen secret. Your job: close every exit. Toggle the egress and tool controls and watch each channel resolve:

Three lessons fall out of playing with it:
- Egress controls alone leave the tools wide open — strip URLs + allowlist, and the agent still emails the data out and hides it in a search query.
- The confused deputy beats the allowlist — a legitimate, allowlisted tool (search) is an exfil channel an allowlist can't see. DLP or least privilege closes it.
- Least privilege is the lever — turning it on removes several exits at once, because most exits are tools. A tool that isn't there can't be abused. No single control wins; you layer them, with least privilege carrying the most weight.
Putting It Together — Assume Breach, Minimize Blast Radius
Step back to the operating philosophy, because it changes how you architect agents:
- Assume the hijack will happen. L240 proved prevention is unreliable, so design as if the agent is compromised. Your security budget goes into containment, not just a better input filter.
- Break the trifecta by design. Put the agent that ingests untrusted content on a path with no private data and no external channel; keep the agent that has private-data access and send tools away from untrusted content (this is the privilege-separation / dual-LLM pattern from L240, applied to the tool layer).
- Layer egress + tool controls (no single one closes every exit), and lean hardest on least privilege.
- Watch the exits in production — log and alert on outbound calls, tool invocations, and approvals (the observability + audit layer from L223 — The Monitoring & Observability Layer and L237 — Model Cards, Audit Logs & Incident Response). A spike in outbound requests or a tool call to a new domain is your exfiltration alarm.
The whole lesson in one line: a hijacked agent that can't reach private data and can't talk to the outside world is harmless. You can't stop the hijack — so make sure it has nowhere to go.
🧪 Try It Yourself
Use the Exfiltration & Tool-Abuse Lab and what you've learned:
- Turn on only the egress controls (strip URLs + allowlist). Which exits close, which stay open, and why isn't that enough?
- Turn on only the egress allowlist. The search-tool channel still leaks — why? What's the name for that?
- Now add least privilege. How many exits does that one toggle close, and what's the principle?
- The markdown-image beacon is blocked by strip-URLs / DLP but not by least-privilege or approval. Why — what kind of bug is the beacon?
- Map the three controls that finally secure everything to the kill-chain step each one stops.
→ (1) The beacon and raw HTTP close, but send_email and the search-query channel stay open — the agent's own tools are exfil channels that egress rules don't govern. (2) Because search is a legitimate, allowlisted tool — the agent hides the secret in a normal query to an approved service. That's the confused deputy: legitimate authority, misused. (3) It closes most of them at once (search, email, HTTP, delete) — the principle is least privilege: a tool that isn't there can't be abused, which is why it's the highest-leverage control. (4) The beacon is an improper-output-handling bug (LLM05): the model just emitted text, and the client rendered a model-supplied URL — it's not a tool call, so tool controls don't touch it. Fix it at output handling (strip URLs) or DLP. (5) Strip-URLs / DLP stops improper output handling (step 3); least privilege stops excessive agency (step 2); and (from L240) input defenses target the injection (step 1) — defense in depth across the whole chain.
Mental-Model Corrections
- “If I block the injection, I'm safe.” You can't reliably block it (L240). Security comes from containment — locking the egress and tools so a hijack does nothing.
- “Exfiltration means a network breach.” It's the agent leaking through its own ordinary channels — an image URL, a search query, an email. Any path outside is an exit.
- “An egress allowlist stops exfiltration.” It stops raw outbound — but a legitimate allowlisted tool (search, email) is still a channel: the confused deputy. Add DLP + least privilege.
- “More tools = more capable = better.” Every tool is attack surface and an exit. Least privilege: give the minimum; a tool that isn't there can't be abused.
- “My tools are from a trusted vendor.” Tool poisoning (hidden instructions in the description) and rug-pulls (behavior changes after approval) mean you must pin & verify tool definitions.
- “The markdown beacon is a model problem.” It's an output-handling problem — the client rendered a model-supplied URL. Strip URLs / don't auto-render.
- “Approval gates everything, so I'm covered.” Approval covers tool actions, not the beacon (an output-rendering leak). You still need egress/output controls — no single layer covers all exits.
Key Takeaways
- A hijack only matters if data gets out or a tool does damage — so defend the lethal trifecta's legs you control: private-data access and external channels / tools. Assume breach; minimize the blast radius.
- The kill-chain is injection → excessive agency → improper output handling — steps 2 & 3 are where the harm happens and where you can lock down hard.
- Exfiltration hides in ordinary channels (markdown-image beacon, a legitimate tool used as a channel, outbound HTTP, email). Lock the egress: strip model-supplied URLs, allowlist outbound, DLP-scan what leaves.
- Tool abuse is the confused deputy — a hijacked agent misuses its own legitimate authority; plus tool poisoning and rug-pulls. Lock the tools: least privilege (the lever), approval gates (L230), pin & verify tool defs, validate params, sandbox.
- No single control closes every exit — layer egress + tool controls, lean on least privilege, and watch the exits in production (L223 / L237). A hijacked agent that can't reach data or phone home is harmless. (Next: Securing Agents & MCP.)