A “local” MCP server sounds like it should be the safe kind — no network exposure, no OAuth grant, nothing to steal remotely. Most local servers run that way, launched over stdio with no open port at all. But a growing number run as a small local HTTP server instead, listening on localhost so a browser-based client or a dev tool can reach it over Streamable HTTP. The moment a server does that, it inherits an old browser-security problem that stdio servers never had to think about: DNS rebinding.
What DNS rebinding actually does
A browser’s same-origin policy decides what a web page’s JavaScript is allowed to talk to based on the page’s origin — scheme, hostname, and port. DNS rebinding abuses the gap between “hostname” and “where that hostname actually points right now.” An attacker runs a domain with a very short DNS TTL, gets a victim to load a page served from it, and once the page’s JavaScript has loaded, flips that domain’s DNS record to resolve to 127.0.0.1 instead. The browser sees the same hostname it started with, decides nothing about the origin has changed, and lets the page’s script keep making requests — except those requests now land on whatever is listening on localhost, on the victim’s own machine.
This isn’t an MCP-specific trick. It’s a known class of attack against any local development server, admin panel, or daemon that binds to a port and trusts “the request came from localhost” as if that meant “the request came from software I trust.” It didn’t mean that before browsers added protections for it, and for a server that skips the fix, it still doesn’t.
Why this lands on MCP specifically
A locally-running MCP server that speaks HTTP is exactly the kind of target this attack was built for: it binds to a port on your machine, it often has no authentication at all because “it’s local, who else can reach it” was the whole threat model, and if it exposes anything resembling file access, shell access, or a write-capable tool, a page that reaches it through DNS rebinding gets the same tool list a legitimate client would. The server never has to be compromised. It just has to answer whoever asks, and DNS rebinding is one way to become “whoever asks” without the user clicking anything or granting any permission.
It’s worth separating this from the risk we covered in SSRF in MCP tools. SSRF is about a tool making an outbound request somewhere it shouldn’t. DNS rebinding is the opposite direction: an inbound request reaching a server that assumed inbound traffic could only ever come from something trustworthy running on the same machine. Same neighborhood — local network trust assumptions — different mechanism.
What the fix actually looks like
None of this requires exotic cryptography. The standard mitigations are the same ones recommended for any local HTTP server with this exposure:
- Validate the
Originheader on every incoming request. A legitimate client knows and sends an expected origin; an attacker’s rebound page is still, from the browser’s perspective, the attacker’s original origin — the server can reject anything that doesn’t match an allow-list instead of trusting that “it reached me” is proof enough. - Bind to
127.0.0.1, not0.0.0.0. Binding to all interfaces makes the server reachable from the local network too, not just the machine it runs on, which widens the same problem rather than fixing it. - Require authentication for local connections too, rather than treating “runs on localhost” as a substitute for it. A shared secret or token the real client already knows is enough to tell it apart from an unrelated page that merely reached the same port.
If you’re building a local MCP server over HTTP, this is the kind of thing worth checking with the MCP Inspector before you ship it: does the server actually look at the Origin header, or does it answer any request that arrives on the port regardless of where it claims to be from?
What this means if you’re only connecting servers, not building them
Most people reading an MCP security post are deciding whether to connect a server, not writing one. For that case, the practical takeaway is narrower: this risk is specific to local servers that run their own HTTP listener, which is a smaller category than “any local server.” A classic stdio server — the kind covered in remote vs. local MCP servers — has no open port and nothing for DNS rebinding to reach. If a local server you’re about to run does open an HTTP port, it’s reasonable to ask the same question you’d ask about any local daemon: does it talk only to processes on this machine that know a shared secret, or does it just answer whoever connects? If the docs don’t say, that silence is itself useful information.
The bottom line
“It only listens on localhost” has never been a complete security argument for a network-facing server, and MCP doesn’t change that. A local server that speaks HTTP instead of stdio needs to check who’s actually asking — a validated Origin header and a real authentication step — the same discipline any local dev server needed before MCP existed. If you’re connecting one, it’s worth asking whether it does. If you’re building one, it’s a few lines of validation, and cheaper to add now than to explain after a browser tab someone else opened managed to reach it.