The MCP security guidance has a section on server-side request forgery. It discusses internal addresses, cloud metadata, redirects and DNS rebinding. The advice is useful. Its OAuth threat model, however, is different from the one facing an MCP tool that accepts an arbitrary URL.
If your tool fetches a page, imports a feed or checks a sitemap, the request originates from your infrastructure. Passing protocol conformance tests does not establish that this fetch is safe.
This is the English edition of our Czech analysis, originally published on 10 September 2026. It distinguishes the specification's guidance, published research and our own implementation recommendations.
Which side of the connection does the specification protect?
The MCP Security Best Practices for revision 2026-07-28 describes an OAuth discovery attack: a malicious server supplies a URL that causes its client to fetch an internal resource. An authorization server retrieving a Client ID Metadata Document faces a related risk.
That makes the fetcher a security boundary. The document recommends validating destinations and redirects, restricting network access and addressing changes in DNS answers between validation and use.
Now turn the connection around:
- A caller invokes your
fetch_pageorimport_from_urltool. - The tool receives a URL as an ordinary argument.
- Your server opens the connection and returns the result.
The protocol can carry that request correctly while the destination is completely inappropriate. Authorization to use a tool is not authorization to access every host reachable from its runtime.
RFC 9728, section 7.7 discusses SSRF in the retrieval of protected-resource metadata. It is relevant guidance for the OAuth path, not a certificate that an application's URL-fetching tools have been secured.
Why an agent makes this boundary easy to miss
The argument may be selected by a model that has just read untrusted material. A page or document can suggest another address to retrieve. The tool implementation still has to decide whether that destination is permitted, regardless of the model's reason for choosing it.
The server may also have access its caller does not: a private service in a VPC, a CI runner's network, a container host or a cloud metadata endpoint. A perimeter firewall does not automatically stop requests originating inside that perimeter.
The useful question is therefore specific: which destinations can this tool reach, through which redirects, from which network identity?
That question remains necessary even when every caller is authenticated.
What the published measurements establish
Nicolás Padilla's July 2026 preprint, Exposed by Design, reports 640 confirmed production MCP servers, 414 dynamically audited servers and 68 reportable vulnerabilities across several classes, including SSRF targeting cloud metadata services. These are different denominators; 68 is not a count of SSRF-vulnerable servers.
The study is a preprint. Its findings support the existence of the failure mode in its measured sample, not a universal prevalence estimate for all MCP deployments. Nor does evidence of an attempted or delayed metadata request, by itself, prove that credentials were extracted.
A separate preprint, A First Measurement Study on Authentication Security in Real-World Remote MCP Servers, examines authentication. Authentication and outbound request restrictions address different boundaries. A finding about one should not be silently presented as a measurement of the other.
Our claim is narrower than a headline percentage: accepting URLs in tools creates an outbound request boundary that needs explicit enforcement.
Six implementation rules
1. Enforce the policy where the connection is opened
Form validation and input schemas are useful for catching mistakes early. They cannot establish where a hostname will resolve when a later process fetches it.
At Stratt Labs, the public intake performs a deliberately limited first check. The scanner that actually opens the connection owns destination enforcement. We do not describe a URL that passed the form as safe to fetch.
Keep this distinction in code, documentation and test names. Otherwise a convenient helper eventually becomes a security guarantee nobody implemented.
2. Validate resolved addresses with an IP-aware library
For a tool intended to fetch public websites, reject destinations outside the allowed public address space. Consider IPv4 and IPv6, loopback, private and link-local networks, cloud metadata paths and shared address space such as 100.64.0.0/10.
A string blacklist is insufficient. URL parsers may normalize alternative forms such as 127.1 or 2130706433. IPv4-mapped IPv6 and translation mechanisms such as NAT64 also deserve tests where the runtime or network supports them; their behavior is not identical in every environment.
Inspect the addresses the runtime can actually connect to. If a name yields a mixture of allowed and disallowed addresses, the connection must never fall back to the disallowed ones.
3. Validate each redirect destination
Checking only the first URL leaves the rest of the journey unguarded. A public endpoint can redirect to a private destination.
Disable automatic redirects when the HTTP client does not expose a safe way to validate every hop. Otherwise, apply the same scheme, address and port policy at each step, with a finite redirect limit.
An HTTP success code from the first host says nothing about the next one.
4. Connect to the address you validated
A DNS answer can change between checking a host and opening the connection. Validating once and allowing the HTTP library to resolve again creates a gap.
Pin the validated destination for the connection using facilities supported by your HTTP client. Preserve the intended hostname for TLS verification and HTTP host handling; bypassing certificate validation would introduce another vulnerability.
If the runtime cannot enforce this, record that limitation and use an outbound proxy or another architecture that can. Do not label the check complete because a DNS lookup happened somewhere earlier in the flow.
5. Restrict outbound access independently
Destination validation benefits from a second boundary: network policy or an egress proxy that blocks access to internal services and metadata endpoints.
A dedicated fetcher should have only the credentials and network access its job requires. Time limits and response-size limits also matter: an allowed host can still keep a connection open or return an excessive body.
This is defense in depth. It reduces the consequences of mistakes in the application check and should be tested as a separate control.
6. Make a security rejection distinguishable from a network failure
This last recommendation comes from our own operational practice. A blocked destination should not disappear into a generic “unreachable” result.
If the guard throws an exception that a broad network-error handler catches, a working control and a broken connection become indistinguishable in the report. Preserve a structured reason for the rejection. Keep sensitive internal details out of public errors while retaining enough evidence for authorized diagnosis.
Our methodology is built around findings that can be checked. A security claim should have an observable outcome, not just a reassuring function name.
A compact regression checklist
For a fetcher whose intended scope is public websites, exercise these cases in an environment you own:
| Case | Expected outcome |
|---|---|
| An allowed public HTTPS destination | Fetch succeeds within resource limits |
| A literal private or loopback address | Rejected before connection |
| A hostname resolving to a disallowed address | Rejected before connection |
| A public URL redirecting to an internal address | Redirect rejected |
| A DNS answer changing after validation | Connection remains pinned or is refused |
| Alternative address notation supported by the runtime | Same policy as the equivalent address |
| A destination rejected by policy | Report identifies a policy rejection |
| An allowed host returning too much data | Fetch terminates at the configured limit |
The point is not to collect a list of dangerous strings. It is to verify that the same destination policy survives parsing, DNS resolution, redirects and the final connection.
What a passing protocol test cannot tell you
Conformance tests are valuable for checking the protocol behaviors they exercise. They cannot infer every network capability hidden inside your tool implementation.
Similarly, a well-written description or a readOnlyHint does not constrain a socket. A tool can avoid changing business data and still disclose a private response.
Treat protocol behavior, directory review and application security as separate questions with separate evidence. Our companion analysis explains why passing MCP conformance does not guarantee directory acceptance. For the broader operational picture, see MCP in production.