OLD BUG, NEW DELIVERY :: SSRF in 36.7% of MCP Servers, and Microsoft's MarkItDown Hands Over AWS Keys
mcpssrfaws-imdscloud-securityai-agents
SSRF is the bug class web AppSec engineers have been writing checks against since 2017. It is in the OWASP Top 10. It is the foundation of countless cloud-credential-exposure incidents — Capital One being the canonical example. Every security team that ships internet-facing services has SSRF guidance in their secure-coding standard. Every assessment includes SSRF testing.
Apparently none of that institutional knowledge transferred to MCP server development.
BlueRock Security scanned over 7,000 publicly exposed MCP servers in early 2026. 36.7% were potentially vulnerable to server-side request forgery. To put a number on the absolute scale: that is over 2,500 vulnerable servers in the publicly accessible sample alone. The real population, including internal deployments, is presumably much larger.
The proof-of-concept that made the disclosure unignorable was the one against Microsoft's MarkItDown MCP server. MarkItDown is an official Microsoft project — open source, hosted under the microsoft org on GitHub, accepted into the MCP ecosystem. It converts file formats to markdown for ingestion by LLM agents. It accepts URLs as input.
It does not validate where those URLs point.
The researchers pointed it at http://169.254.169.254/ — the AWS EC2 instance metadata endpoint. MarkItDown dutifully fetched the URL. The instance metadata service returned IAM role credentials. MarkItDown returned those credentials to the agent. The agent — or anyone with the ability to feed prompts to the agent — now has AWS IAM access keys, secret keys, and session tokens for the role attached to whatever EC2 instance is hosting the MarkItDown deployment.
Capital One 2019, the bug. MCP server 2026, the bug. Same bug class. Same root cause. Same blast radius. Different delivery mechanism.
Why MCP makes SSRF worse
Traditional SSRF requires an attacker to find an internet-facing endpoint, identify the URL-fetching parameter, and craft a request. The exploit is a series of curl commands or a Burp Repeater session. The defense is to inspect the input, restrict the destinations, validate the URL parser, block IMDSv1, force IMDSv2, set hop limit to 1.
MCP changes the access path. The attacker does not need to find the endpoint. The attacker does not need to craft the request. The attacker tells an LLM agent — using whatever channel the attacker has into the agent's context, which includes prompt injection through documents, retrieved content, tool outputs, and indirect channels — to do something whose execution path happens to traverse the MCP server's URL-fetching code.
The MCP server runs in the agent's network position. That position usually includes:
- The cloud metadata endpoint of the host instance
- Internal VPC services not exposed to the public internet
- The Kubernetes API if running in a cluster
- Internal admin panels, monitoring dashboards, CI/CD interfaces
- Localhost services on the same machine — Redis, databases, debugging endpoints
The agent's network reachability is the attacker's network reachability, modulo whatever the MCP server's URL parser will accept.
What MarkItDown should have done
The standard SSRF mitigation checklist applies. None of it is novel. All of it should have been in the original implementation:
- Reject URLs that resolve to private IP ranges:
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.0/8,169.254.0.0/16,::1,fc00::/7,fe80::/10 - Reject URLs that resolve to cloud metadata endpoints by IP, not just by hostname — DNS rebinding attacks defeat hostname-based blocklists
- Resolve the URL once, check the resolved IP, then connect to that resolved IP — do not give the URL parser two chances to resolve different addresses
- Block IMDSv1 at the EC2 instance level, force IMDSv2, set hop limit to 1 so even compromised processes cannot reach metadata through routed traffic
- Run the MCP server with the minimum IAM role required for its actual function — for a markdown converter, the answer is "no IAM role at all"
- Network segmentation that places MCP servers in subnets without access to internal services they do not need
The wider lesson
This is not the only classical web vulnerability hiding in MCP server implementations. Path traversal, command injection, deserialization, XXE — all of it is showing up in MCP-server form, because MCP servers are being written by developers who treat them as internal tools rather than as internet-exposed services.
They are internet-exposed services. Once an LLM agent can be prompted by content the developer does not control — and that is the default condition of nearly every agent deployment — the MCP server is reachable through that prompt-injection path. The same threat model applies as to any public HTTP service.
If you are running MCP servers in production:
- Inventory them all
- Assess each one against the standard OWASP API and web vulnerability list
- Assume prompt injection is achievable; design the MCP server's threat model accordingly
- Containerize, sandbox, segment, and credential-isolate every MCP server
- Block IMDSv1 across all cloud accounts hosting MCP infrastructure
- Monitor outbound network from MCP server hosts; alert on attempts to reach internal addresses
None of this is new advice. The advice has not become new. The deployment context has. Update accordingly.