Now in early access, book a 30-minute demo →
← Back to blog AdvisoryHigh

MCP fURI: SSRF in Microsoft's MarkItDown Server, and the 36.7% of MCP Servers Sharing the Pattern

MCP Server Security·High·MCP fURI (BlueRock Security) - SSRF in Microsoft MarkItDown MCP; ecosystem-scale pattern·
Affected Microsoft MarkItDown MCP server; BlueRock reports ~36.7% of 7,000+ analysed MCP servers may share the pattern, and 33% SSRF / 42% command injection / 6% critical across a wider 12,000+ server set

BlueRock Security disclosed MCP fURI, a server-side request forgery flaw in Microsoft's MarkItDown MCP server - a widely used tool that converts files to Markdown for LLMs, from a repository with 85,000+ GitHub stars. The server accepts a URI and fetches it without validating the input, so anything that can influence that parameter can make the server issue requests on its behalf. BlueRock demonstrated the consequence on AWS EC2: pointing MarkItDown at the instance metadata service returned IAM credentials, including access keys and session tokens. The finding that matters more than the single bug is the scale - BlueRock reports roughly 36.7% of over 7,000 analysed MCP servers may contain the same pattern.

What happened

MarkItDown does something entirely reasonable: it takes a pointer to a document and returns Markdown an LLM can read. To do that it must fetch the thing being pointed at. The flaw is that it fetches whatever URI it is given, with no validation of the destination - no allow-list, no scheme restriction, no block on link-local or internal addresses.

That is a textbook SSRF, and in a cloud environment the textbook target is the instance metadata service. BlueRock pointed the server at the IMDS address on an EC2 instance and retrieved IAM access keys and session tokens belonging to the instance role. From there an attacker holds whatever that role can do. The chain is short because the server is running inside your network with your credentials, which is precisely the property that makes MCP servers useful.

The reason this is an *ecosystem* advisory rather than a product one is what BlueRock found when they looked wider. Their analysis of 7,000+ MCP servers suggests approximately 36.7% may contain similar SSRF exposure. A broader pass across 12,000+ public MCP servers reported 33% vulnerable to SSRF, 42% with command injection flaws, and 6% with critical vulnerabilities. Treat those as two studies of different scope rather than one number - the SSRF figures differ because the sample sizes do - but the direction is unambiguous and consistent.

The pattern repeats because the MCP tool contract encourages it. A tool advertises a parameter, the model supplies a value, the server acts on it. Fetch this URL, read this path, run this query are the three most natural MCP tools to write, and each is an injection sink if the parameter is trusted. Nothing about MCP requires validation, and a server author writing a fetch tool has no obvious prompt to add it.

DetailValue
NameMCP fURI
Reported byBlueRock Security
Anchor productMicrosoft MarkItDown MCP server (85,000+ GitHub stars)
FlawAccepts a URI and fetches it without validating the destination
Demonstrated impactSSRF to the EC2 instance metadata service, returning IAM access keys and session tokens
Ecosystem - SSRF~36.7% of 7,000+ analysed MCP servers may share the pattern
Ecosystem - wider setAcross 12,000+ public servers: 33% SSRF, 42% command injection, 6% critical
Root cause classMCP tool parameters treated as trusted input

Why this is an agentic-endpoint risk

SSRF is a well-understood bug class with well-understood fixes, and that is exactly why the ecosystem numbers are the story. This is not a novel technique - it is a 1990s-vintage vulnerability class reintroduced at scale because a new component type shipped fast without the validation habits web services acquired the hard way. The MCP ecosystem is largely individual authors publishing single-purpose servers, and secure-by-default is not a property you get from enthusiasm.

There is a second reason it is worse in an agent context. Classic SSRF requires an attacker to reach the vulnerable parameter through your application. Here the model supplies the parameter, and the model reads untrusted content - web pages, documents, tool results, repository files. So indirect prompt injection becomes a remote trigger for SSRF: text on a page can cause the agent to call a fetch tool with an attacker-chosen URI. The attacker never touches your network. The DuneSlide and Kiro findings established that MCP responses and fetched pages are viable injection channels; a vulnerable fetch tool is what turns that channel into cloud credential theft. The mechanism is covered in indirect prompt injection explained.

The practical exposure question is therefore not *is MarkItDown patched*. It is which MCP servers are running across our fleet, which of them fetch or read on a model-supplied parameter, and what network and credentials can they reach. Almost nobody can answer the first part, which is why the rest goes unasked. MCP servers are one of the eight AI artifact types Anomity inventories per endpoint, and they spread the way AI agents became the new shadow IT - per developer, per project, uncounted.

How Anomity surfaces and governs it

First, inventory the servers. With a third of the public ecosystem plausibly carrying this pattern, the useful control is not tracking individual CVEs - it is knowing which servers you run at all. Anomity's unprivileged Endpoint Sensor runs on Windows, macOS and Linux and inventories MCP servers alongside AI agents, extensions, plugins, skills, secrets, hooks and CLIs, each with a first-seen timestamp and the endpoint it appeared on. That turns "are we exposed to a class affecting a third of servers" from unanswerable into a query.

Second, decide at the tool call. You cannot audit thousands of third-party servers, but you can constrain what they do. Where an agent exposes a hook - for example the PreToolUse event in Claude Code - Anomity evaluates each call against policy and returns allow, deny, or log before it runs. A fetch tool invoked against a link-local metadata address, or a server reaching for credentials it has no business touching, is denied at the boundary regardless of what the parameter says or which prompt produced it. That is runtime governance applied to an unvetted supply chain.

Third, keep the record. Artifact changes and policy decisions land in a queryable 90-day audit trail, so when the next ecosystem study lands you can scope exposure from a record. Anomity collects metadata only, with on-endpoint secret redaction, so the cloud credentials this class targets are never centralized. Findings route to SIEM, Slack, email, or Jira, the platform is SOC 2 Type II, and it complements EDR, DLP, network and GRC tooling. See how it works.

You can't govern what you can't see.The Anomity principle

What to check across your fleet

  • Enumerate every MCP server running across endpoints and CI, then triage by capability rather than popularity: which ones fetch a URL, read a path, or run a query using a model-supplied parameter?
  • Update Microsoft MarkItDown MCP wherever it is deployed, and check for the same unvalidated-fetch pattern in any other document-conversion or URL-fetching server you run.
  • Enforce IMDSv2 with hop limits on cloud instances, and block link-local and internal address ranges at the egress path available to MCP servers - SSRF to metadata is the highest-value target and the easiest to close.
  • Give MCP servers their own least-privileged credentials rather than inheriting an instance role or a developer's shell environment; over stdio a server inherits environment variables, so a broad role becomes the server's role.
  • Rotate any IAM credentials reachable from a host that ran an unvalidated fetch tool with agent access to untrusted content.
  • Treat model-supplied tool parameters as untrusted input in your own MCP servers - allow-list schemes and destinations, and deny link-local, loopback and internal ranges by default.
  • Move to a reviewed set of servers rather than per-developer discretion, per building an MCP server registry, and re-check it as the ecosystem numbers change.
  • Confirm tool calls are evaluated at a hook with allow/deny/log so a vulnerable third-party server still meets a boundary - see Claude Code permissions and hooks hardening and least privilege for AI agents.

MCP fURI is an ordinary SSRF in an extraordinary position: inside your network, holding your credentials, with its input parameter chosen by a model that reads untrusted text. The single bug is fixable. The 36.7% is not something you patch - it is something you design around, by inventorying which servers you run, constraining what they may reach, and treating tool parameters as hostile in the servers you write. For the full trust model see the MCP Server Security guide, for the protocol's new shape stateless MCP, and for lifecycle placement ADLC. To see which MCP servers your fleet actually runs, request early access.

Frequently asked questions

What is MCP fURI?

MCP fURI is the name BlueRock Security gave to a server-side request forgery vulnerability in Microsoft's MarkItDown MCP server, a widely used tool that converts files to Markdown for LLM consumption from a repository with more than 85,000 GitHub stars. The server accepts a URI parameter and fetches it without validating the destination - no allow-list, no scheme restriction, and no block on link-local or internal addresses. BlueRock demonstrated the impact on AWS EC2 by pointing the server at the instance metadata service, which returned IAM credentials including access keys and session tokens belonging to the instance role.

How widespread is the pattern across MCP servers?

BlueRock's analysis of more than 7,000 MCP servers suggests approximately 36.7% may contain similar SSRF exposure. A separate, broader pass across more than 12,000 public MCP servers reported 33% vulnerable to SSRF, 42% carrying command injection flaws, and 6% containing critical vulnerabilities. Those SSRF percentages differ because the sample scopes differ, so treat them as two studies rather than one figure - but the direction is consistent, and it means roughly a third of the public ecosystem plausibly shares this class. That is why the useful response is inventory and constraint rather than tracking individual CVEs.

Why is SSRF worse in an MCP server than in a normal web service?

Two reasons. First, position: an MCP server runs inside your network, launched as a local child process with the user's permissions, inheriting environment variables over stdio and reachable network paths. So the request it can be tricked into making starts from a privileged vantage point, which is exactly why metadata-service access yields cloud credentials. Second, the trigger: in a classic web service an attacker must reach the vulnerable parameter through your application, whereas here the model supplies the parameter and the model reads untrusted content. Indirect prompt injection therefore becomes a remote trigger - text on a fetched page can cause the agent to call a fetch tool with an attacker-chosen URI, and the attacker never touches your network.

What should we do if we run MarkItDown?

Update it wherever it is deployed, then treat the wider pattern rather than the single server. Enforce IMDSv2 with hop limits so metadata access is materially harder, and block link-local, loopback and internal ranges on the egress path available to MCP servers. Give servers their own least-privileged credentials instead of letting them inherit an instance role or a developer's shell environment. And rotate any IAM credentials reachable from a host that ran an unvalidated fetch tool while the agent had access to untrusted content, since you cannot distinguish exploitation from normal use after the fact.

How do we prevent this in MCP servers we write ourselves?

Treat every model-supplied tool parameter as untrusted input, because that is exactly what it is - the value originates from a model that reads web pages, documents and tool results. For fetch tools, allow-list schemes and destinations rather than blocking known-bad, and deny link-local, loopback and internal address ranges by default. For file tools, validate and canonicalise paths, and make sure the check fails closed when resolution errors. For query tools, parameterise. None of this is novel; it is the validation discipline web services acquired over two decades, applied to a component type that shipped fast without it.

Can we realistically audit every MCP server we use?

No, and that is the point. With roughly a third of the public ecosystem plausibly affected by one class alone, per-server auditing does not scale and neither does CVE tracking. Two things do. First, inventory: know which servers actually run across your endpoints and CI, with first-seen timestamps, so you can scope exposure when the next study lands instead of guessing. Second, constraint at the point of action: evaluate each tool call against policy and return allow, deny or log before it runs, so a vulnerable third-party server reaching for a metadata address or a credential file is stopped regardless of its code quality. Inventory plus enforcement is how you handle an unvetted supply chain you did not write.

Ask AI about Anomity
ChatGPT Claude Perplexity Google AI Grok