MCP Markdownify SSRF Tool Invocation
An AI agent tool that converts web pages to markdown can be tricked into fetching internal network resources instead of public pages. If a prompt (including one hidden in content the agent processes) supplies a URL pointing at internal infrastructure, the tool fetches it and hands the response back as text.
How the attack works
The mcp-markdownify-server exposes tools like webpage-to-markdown, bing-search-to-markdown, and youtube-to-markdown that take a URL and fetch it server-side. In versions before 1.0.0, that URL is passed straight to the fetch logic with no validation. An attacker who can influence the URL argument - directly or via injected content the agent reads - can point it at loopback addresses, private IP ranges, cloud metadata endpoints (like 169.254.169.254), or non-HTTP schemes such as file:// or gopher://. The server fetches that target from its own network position and returns the content as markdown, effectively letting the attacker read internal resources through the agent.
Netzilo detection
Netzilo reports this behaviour when it is observed.
- Signature ID
- 7c1e4d9a-3b62-4f81-9e0c-2a5d8f14b6e3
- Severity
- High
Why it matters
An attacker can read internal-only web content, cloud metadata (including credentials in some cloud setups), or local files reachable from the server, using the AI agent as a proxy into the internal network.
What you can do
- →Upgrade mcp-markdownify-server to 1.0.0 or later, or apply URL validation in front of it if you cannot upgrade immediately.
- →Block or filter outbound requests from the agent host to loopback, RFC1918, link-local, and cloud metadata addresses at the network layer.
- →Restrict which schemes the fetch tool accepts (allow http/https only, reject file:, gopher:, dict:, ldap:, etc.).
- →If internal wiki or intranet conversion is a legitimate use case, scope the tool to an explicit allowlist of internal hosts rather than allowing arbitrary URLs.
Known benign look-alikes
- Developer converting a locally hosted docs/site preview (http://localhost:3000, http://127.0.0.1:8080) with markdownify - genuinely benign but indistinguishable from loopback SSRF at the single-event content layer. This is the main reason the rule reports rather than blocks.
- Deployments intentionally scoped to an intranet wiki or internal knowledge base (*.corp, *.internal, dotless service names such as http://confluence/) where converting internal pages is the designed use case.
- Security regression suites and pentest harnesses that deliberately fire 169.254.169.254 / file:// payloads at the markdownify tools to verify the fix.
- MCP capability enumeration or tool-catalog payloads that echo the tool names next to example URLs - suppressed by filter_discovery and filter_schema.
- Automation templates where the URL argument is still an unexpanded variable or documented placeholder - suppressed by filter_placeholder.
- Authenticated internal fetches expressed with userinfo credentials (http://user:pass@host/) - matched by the userinfo branch; treat as review-worthy rather than malicious.