CrawlForge MCP
HomePlaygroundUse CasesIntegrationsPricingDocumentationBlog
SSRF in MCP Servers: Why Scrapers Leak Cloud Secrets
AI Engineering
Back to Blog
AI Engineering

SSRF in MCP Servers: Why Scrapers Leak Cloud Secrets

C
CrawlForge Team
Engineering Team
August 13, 2026
9 min read

On this page

Quick Answer

A July 2026 arXiv study (arXiv:2608.00150) dynamically audited 414 internet-facing MCP servers and found 68 reportable vulnerabilities, with 91.8% lacking OAuth authentication entirely. Web-scraping MCP servers are the most exposed class because fetching a model-supplied URL is their advertised feature: a page the agent reads can carry prompt-injected instructions that steer the server to cloud metadata endpoints, and the response flows straight back into the model's context. CVE-2026-65056 documents exactly this chain in mcp-webresearch 0.1.7, which validated only the URL protocol. Effective defenses block by resolved IP range rather than hostname, check IP literals and IPv4-mapped IPv6, pin connections to the validated IP, re-validate every redirect hop, and guard browser navigation separately.

In July 2026, a security researcher pointed a purpose-built scanner at every MCP server they could find on the public internet. They confirmed 640 production servers, dynamically audited 414 of them, and found 68 reportable vulnerabilities — SQL injection, prompt template injection, path traversal, and SSRF aimed squarely at cloud metadata services.

The number that should stop you: 91.8% of the servers they audited had no OAuth authentication at all.

If you run or build a web-scraping MCP server, this is your problem more than anyone else's. A scraping tool's entire job is to take a URL and fetch it. When the URL argument is chosen by a language model, and that model can be influenced by the content of pages it reads, you have built a server-side request forgery machine and handed the steering wheel to an attacker.

Table of contents

  • The state of MCP server security in 2026
  • Why scraping servers are the worst case
  • Anatomy of a real CVE
  • The bypass ladder: six ways a URL check fails
  • A defense checklist that actually holds
  • How CrawlForge implements this
  • If you are a user, not an author

The state of MCP server security in 2026

The study is Exposed by Design: A Dynamic Security Assessment of Internet-Facing MCP Servers at Scale (Nicolás Padilla, arXiv:2608.00150, submitted 31 July 2026). It is the first dynamic behavioral assessment of MCP servers in the wild, rather than a static read of source code.

The method was passive discovery across eleven data sources — certificate transparency logs, GitHub, npm, PyPI, HuggingFace, Smithery, Censys, FOFA, Shodan and others — followed by active testing with Corvus, a framework of 34 test modules covering 10 MCP-specific vulnerability classes.

What it found across four measurement runs:

FindingFigure
MCP server instances detectable on the public internet21,000+
Production servers confirmed640
Servers dynamically audited414
Reportable vulnerabilities found68
Audited servers with no OAuth authentication91.8%
Tool instances exposing shell execution without access controls687
Confirmed servers that vanished within three days41.6%

That last row is the one people skip past, and it is arguably the most revealing. Four in ten servers disappeared between consecutive measurement runs — the signature of software being deployed straight to the internet without a security review, then pulled down.

Why scraping servers are the worst case

Most SSRF advice assumes a web application where the attacker has to find some obscure parameter that gets fetched server-side. A scraping MCP server inverts that completely: fetching an attacker-supplied URL is the advertised feature.

Three properties stack up badly:

The URL is model-controlled. Your tool schema says url: string. The model fills it in. Nothing in the protocol distinguishes a URL the user typed from one the model invented.

The model reads untrusted text. This is the part that turns a design property into an exploit. Your agent scrapes a page; that page contains text instructing the model to fetch http://169.254.169.254/latest/meta-data/iam/security-credentials/; the model complies. That is prompt injection converted directly into SSRF, and the request originates from inside your network with whatever credentials your instance carries.

The output goes straight back into the model's context. A classic SSRF is blind — you often cannot see the response. Here, the response body is returned to the model as tool output, and from there into the conversation, the logs, and potentially the next tool call. Exfiltration is built in.

Cloud metadata endpoints are the obvious target because they are unauthenticated by design and sit at a fixed, well-known address on every major provider. But the same primitive reaches internal admin panels, Redis on localhost, Kubernetes API servers, and anything else that trusted the network perimeter.

Anatomy of a real CVE

CVE-2026-65056 (published 21 July 2026, CWE-918, CVSS 4.0 base score 8.3 HIGH) describes this end to end in a real package. The affected software is mcp-webresearch at version 0.1.7 and below.

From the NVD record, the flaw is that the visit_page tool only validates the URL protocol — it checks that you passed http: or https: and never filters private or reserved IP ranges. The advisory then spells out the full chain: an attacker steers the LLM-controlled URL argument through prompt injection, the server's Playwright browser navigates to an internal endpoint such as a cloud instance metadata service, and the sensitive internal page content — credentials included — is returned into the model context.

That is not a theoretical attack path. That is the CVE description.

It is not an isolated case either. CVE-2026-26118 is server-side request forgery in Microsoft's own Azure MCP Server, rated CVSS 3.1 8.8 HIGH, also CWE-918, fixed in 1.0.2 and 2.0.0-beta.17. If Microsoft shipped an SSRF in an official MCP server, the odds that a weekend-project scraping server got it right are not good.

The bypass ladder: six ways a URL check fails

Here is the uncomfortable part. Most developers who do add SSRF protection add rung one or two of this ladder and stop. Each rung below is a real bypass of the rung above it.

1. Protocol-only validation. Checking for http:/https: and nothing else. This is exactly CVE-2026-65056. It stops file:// and gopher:// and nothing that matters here.

2. Hostname string blocklists. Blocking the literal strings localhost and 127.0.0.1. Trivially bypassed, because an IP address has many spellings.

3. Alternate IP literal encodings. 127.0.0.1 is also 2130706433 in decimal and 0x7f000001 in hex. The WHATWG URL parser — the one built into every modern runtime — normalizes all of these to the same address after your string check has already passed. Worse, in Node.js an IP literal never goes through DNS resolution, so guards that hook the lookup call see nothing at all.

4. IPv4-mapped IPv6. ::ffff:127.0.0.1 and ::ffff:169.254.169.254 embed an IPv4 address inside IPv6 notation. A range check that only understands dotted-quad IPv4 waves these straight through. This also opens a DNS-controlled variant: an attacker publishes an AAAA record pointing at a mapped internal address.

5. DNS rebinding (TOCTOU). You resolve the hostname, confirm it is a public address, approve it — and then the HTTP client resolves it again when it actually connects. With a short TTL, the attacker returns a public IP on the first lookup and an internal one on the second. The only durable fix is to check and then pin the connection to the validated IP, so the address you approved is the address you connect to.

6. Redirect hops. You validate the URL you were given. The server returns 302 Location: http://169.254.169.254/. Unless every hop is re-validated — and unless an allowlisted first hop does not silently unguard the rest of the chain — you have simply moved the vulnerability one step downstream.

There is a seventh case specific to browser automation: if your tool drives Playwright or Puppeteer, the browser performs its own navigation. Guarding your fetch wrapper does nothing. You need a pre-navigation check and a post-navigation re-read of the actual URL, because client-side redirects and meta-refreshes happen inside the page.

A defense checklist that actually holds

[ ] Block by resolved IP range, never by hostname string [ ] Run the range check on IP-literal hosts too — they skip DNS entirely [ ] Normalize IPv4-mapped IPv6 before any range comparison [ ] Pin the connection to the validated IP (defeats DNS rebinding) [ ] Re-validate every redirect hop, not just the first URL [ ] Scope allowlists per-hop, so one trusted host does not unguard the chain [ ] Guard browser navigation separately, with a post-navigation URL re-check [ ] Block 169.254.0.0/16 (metadata), loopback, and 0.0.0.0 by default [ ] Offer strict mode: full RFC1918 and IPv6 ULA private ranges [ ] Put a deadline and a size cap on every response body read [ ] Mask secrets before any telemetry or log write [ ] Require authentication — 91.8% of audited servers do not

The ranges worth blocking by default are loopback (127.0.0.0/8, ::1), link-local including cloud metadata (169.254.0.0/16), and the unspecified address 0.0.0.0. Full private-range blocking (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fc00::/7) should be available as a strict mode — plenty of legitimate deployments do need to scrape an internal staging host, and a guard nobody can configure is a guard people disable entirely.

How CrawlForge implements this

We are not writing this from the sidelines. CrawlForge's v5.0.0 release was a seven-phase remediation program, and its first phase was exactly this class of bug — including one we had shipped ourselves.

Our SSRF guard resolved hostnames and checked the resulting addresses, but did not run the same check when the host was already an IP literal. That is rung three of the ladder above, and it was live in our code. Phase 1 fixed it by running the range check on IP-literal hostnames at pre-flight and, separately, wrapping the undici dispatcher's buildConnector with a per-connect check — so a redirect hop straight to an internal address is caught at connection time even though Node never routed it through DNS.

The rest of the ladder is covered as follows:

  • IPv4-mapped IPv6 normalizes to the embedded IPv4 before range checks, in both default and strict modes.
  • Connections pin to the validated IP, closing the DNS-rebinding window.
  • Allowlists are evaluated per hop — an approved first hop no longer unguards the redirect chain.
  • Browser navigation is guarded independently: scrape_with_actions validates before page.goto and re-reads page.url() afterward, closing the page if navigation landed in a blocked range.
  • Every fetching subsystem is wired in — page and metadata fetches, PDF downloads, webhook delivery, and research notifications each go through the guard rather than raw fetch.
  • Secrets are masked before usage telemetry leaves the process.

Defaults block loopback, link-local/metadata, and 0.0.0.0. SSRF_STRICT=true adds full RFC1918 and ULA enforcement, ALLOWED_DOMAINS allowlists trusted internal hosts, and SSRF_PROTECTION_ENABLED=false exists as a kill switch for people who genuinely need one.

Bash
SSRF_STRICT=true                    # full private-range enforcement
ALLOWED_DOMAINS=staging.acme.dev    # trusted internal targets

If you are a user, not an author

You do not need to read anyone's source code to reduce your exposure meaningfully.

Audit what you have connected. Every MCP server in your client config runs with your machine's network access and your credentials. On a cloud VM or a corporate VPN, that reach is much wider than on a laptop.

Prefer servers that publish a security posture. A changelog that names the CVE classes it has closed tells you more than a feature list. Silence is not evidence of safety — given the study's numbers, silence is closer to evidence of the opposite.

Reduce the attack surface you expose to the model. If a server supports tool whitelisting, use it. CrawlForge takes CRAWLFORGE_TOOLS or CRAWLFORGE_TOOL_GROUPS to expose only the tools you actually need, which both cuts context bloat and shrinks what a prompt-injected model can reach for.

Treat scraped content as hostile input. It is the single most important mental shift here. Any page your agent reads can contain instructions aimed at your model. Every one of the attacks above depends on that, and no amount of network hardening fixes a workflow that pipes scraped text straight into a tool call with no review.


Building agents that read the live web? Start free with 1,000 credits — SSRF protection on by default, no configuration required. See the full docs, the scrape_with_actions reference, or how we handle anti-bot detection in stealth mode.

Try this yourself — no signup needed

Run any of CrawlForge's 30 scraping and extraction tools in the playground, then start free with 1,000 credits.

1,000 free credits • One-time • No credit card required

Tags

securitySSRFMCPweb-scrapingAI agents

About the Author

C

CrawlForge Team

Engineering Team

Building the most comprehensive web scraping MCP server. We create tools that help developers extract, analyze, and transform web data for AI applications.

Stay updated with the latest insights

Get tutorials, product updates, and web scraping tips delivered to your inbox.

No spam. Unsubscribe anytime.

Put this into practice

Test CrawlForge's tools on any URL — free, no signup.

On this page

Frequently Asked Questions

What is SSRF in the context of an MCP server?+

Server-side request forgery (CWE-918) is when an attacker induces a server to make HTTP requests to destinations the attacker chooses. In an MCP scraping server the risk is structural rather than incidental: the tool's job is to fetch a URL, and that URL argument is filled in by a language model. If the model reads attacker-controlled page content containing injected instructions, it can be steered into fetching internal addresses such as cloud metadata endpoints. The response then returns to the model as tool output, so unlike classic blind SSRF, exfiltration is built into the design.

How many MCP servers actually have security problems?+

The arXiv study Exposed by Design (arXiv:2608.00150, submitted 31 July 2026) discovered over 21,000 MCP server instances on the public internet, confirmed 640 as production servers, and dynamically audited 414 of them using a 34-module test framework. It found 68 reportable vulnerabilities including SQL injection, SSRF against cloud metadata services, prompt template injection, and path traversal. 91.8% of the audited servers had no OAuth authentication, 687 tool instances exposed shell execution without access controls, and 41.6% of confirmed servers disappeared within three days between measurement runs.

Why is blocking localhost and 127.0.0.1 not enough?+

Because an IP address has many valid spellings, and the URL parser normalizes them after your string check has already passed. 127.0.0.1 is also 2130706433 in decimal and 0x7f000001 in hexadecimal. IPv4-mapped IPv6 notation such as ::ffff:169.254.169.254 embeds an IPv4 address in a form that dotted-quad range checks miss entirely. In Node.js, IP literals never go through DNS resolution, so guards hooked into the lookup call see nothing. Beyond encoding, DNS rebinding lets an attacker return a public address on your validation lookup and an internal one on the actual connection, and a redirect hop can move the request to an internal target after validation has passed.

What is DNS rebinding and how do I defend against it?+

DNS rebinding is a time-of-check to time-of-use attack. You resolve a hostname, confirm the address is public, and approve the request — but the HTTP client resolves the hostname again when it actually opens the connection. With a short TTL the attacker returns a public IP for the first lookup and an internal one for the second, so the request you approved is not the request that gets made. String or hostname checks cannot close this window. The durable fix is to pin the connection to the specific IP address you validated, so the approved address is the one actually connected to.

Is CrawlForge's SSRF protection enabled by default?+

Yes. Protection is on by default and blocks loopback, link-local and cloud metadata addresses (169.254.0.0/16), and 0.0.0.0, with no configuration required. Set SSRF_STRICT=true to add full RFC1918 and IPv6 ULA private-range enforcement, use ALLOWED_DOMAINS to allowlist trusted internal hosts, and SSRF_PROTECTION_ENABLED=false exists as a kill switch. The guard runs on IP-literal hosts as well as resolved hostnames, normalizes IPv4-mapped IPv6, pins connections to the validated IP, evaluates allowlists per redirect hop, and guards Playwright navigation separately with a post-navigation URL re-check.

Related Articles

Reddit Data for AI Agents: The MCP Route
AI Engineering

Reddit Data for AI Agents: The MCP Route

Reddit is where the unfiltered opinions live, and it is the most agent-hostile mainstream site on the web. Here is how to give your AI agent working Reddit search — posts, comments, and full threads — through one MCP tool.

C
CrawlForge Team
|
Aug 24
|
6m
Agent Scraper: What It Is and How to Build One
AI Engineering

Agent Scraper: What It Is and How to Build One

An agent scraper follows a goal, not a selector. What that means, the three ways to build one, working code, the real failure modes, and the credit math.

C
CrawlForge Team
|
Aug 22
|
13m
Best Web Scraping Tools for AI Agents in 2026
AI Engineering

Best Web Scraping Tools for AI Agents in 2026

The best web scraping tools for AI agents in 2026, ranked by agent-readiness: MCP-native tool discovery, typed schemas, and token-efficient output.

C
CrawlForge Team
|
Jun 9
|
11m

Footer

CrawlForge MCP

Enterprise web scraping for AI Agents. 30 specialized MCP tools designed for modern developers building intelligent systems.

Product

  • Features
  • Playground
  • Pricing
  • Use Cases
  • Integrations
  • Alternatives
  • Changelog

Resources

  • Getting Started
  • API Reference
  • Templates
  • Guides
  • Blog
  • Glossary
  • FAQ
  • Sitemap

Developers

  • MCP Protocol
  • Claude Desktop
  • Cursor IDE
  • LangChain
  • LlamaIndex

Company

  • About
  • Contact
  • Privacy
  • Terms
  • Acceptable Use
  • Security
  • Cookies

Stay updated

Get the latest updates on new tools and features.

Built with Next.js and MCP protocol

© 2025-2026 CrawlForge. All rights reserved.