DNS Rebinding Protection Disabled by Default in Model Context Protocol Python SDK for Servers Running on Localhost
Description
The MCP Python SDK, called mcp on PyPI, is a Python implementation of the Model Context Protocol (MCP). Prior to version 1.23.0, tThe Model Context Protocol (MCP) Python SDK does not enable DNS rebinding protection by default for HTTP-based servers. When an HTTP-based MCP server is run on localhost without authentication using FastMCP with streamable HTTP or SSE transport, and has not configured TransportSecuritySettings, a malicious website could exploit DNS rebinding to bypass same-origin policy restrictions and send requests to the local MCP server. This could allow an attacker to invoke tools or access resources exposed by the MCP server on behalf of the user in those limited circumstances. Note that running HTTP-based MCP servers locally without authentication is not recommended per MCP security best practices. This issue does not affect servers using stdio transport. This vulnerability is fixed in 1.23.0.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
MCP Python SDK prior to 1.23.0 lacks default DNS rebinding protection for HTTP-based servers on localhost, enabling remote exploitation.
Vulnerability
Overview
The MCP Python SDK (package mcp on PyPI) prior to version 1.23.0 fails to enable DNS rebinding protection by default for HTTP-based servers [1][2][4]. When a FastMCP server is run on localhost without authentication using streamable HTTP or SSE transport, and without explicit TransportSecuritySettings, a malicious website can leverage DNS rebinding to bypass the browser's same-origin policy and send requests to the local MCP server [2][4]. This bypass occurs because the server does not validate the origin of incoming requests, allowing a remote attacker-controlled domain to resolve to the localhost address and interact with the server as if it were from the same origin.
Exploitation
Conditions
Exploitation requires the MCP server to be running on localhost with HTTP transport (streamable HTTP or SSE), without authentication, and without manual configuration of TransportSecuritySettings [2][4]. The attacker must entice a user to visit a malicious website while the vulnerable MCP server is active locally. The server must be exposed via FastMCP API; servers using stdio transport are unaffected [2][4].
Impact
If successfully exploited, an attacker can invoke tools, read resources, or perform other actions exposed by the MCP server, impersonating the legitimate user [2][4]. The impact is limited to unauthenticated, locally-bound HTTP servers, but could lead to unauthorized data access or tool execution within the context of the victim's session.
Mitigation
The vulnerability is fixed in MCP Python SDK version 1.23.0 [2][3][4]. The fix automatically enables DNS rebinding protection when the server host is set to 127.0.0.1, localhost, or ::1, populating allowed_hosts and allowed_origins with appropriate values [3]. Users should update to version 1.23.0 or later. For custom low-level server configurations that use StreamableHTTPSessionManager or SseServerTransport directly, administrators should explicitly configure TransportSecuritySettings with DNS rebinding protection enabled [4].
- GitHub - modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients
- NVD - CVE-2025-66416
- Merge commit from fork · modelcontextprotocol/python-sdk@d3a1841
- DNS Rebinding Protection Disabled by Default in Model Context Protocol Python SDK for Servers Running on Localhost
AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
mcpPyPI | < 1.23.0 | 1.23.0 |
Affected products
2- Range: <1.23.0
- modelcontextprotocol/python-sdkv5Range: < 1.23.0
Patches
1d3a184119e44Merge commit from fork
2 files changed · +55 −0
src/mcp/server/fastmcp/server.py+8 −0 modified@@ -174,6 +174,14 @@ def __init__( # noqa: PLR0913 auth: AuthSettings | None = None, transport_security: TransportSecuritySettings | None = None, ): + # Auto-enable DNS rebinding protection for localhost (IPv4 and IPv6) + if transport_security is None and host in ("127.0.0.1", "localhost", "::1"): + transport_security = TransportSecuritySettings( + enable_dns_rebinding_protection=True, + allowed_hosts=["127.0.0.1:*", "localhost:*", "[::1]:*"], + allowed_origins=["http://127.0.0.1:*", "http://localhost:*", "http://[::1]:*"], + ) + self.settings = Settings( debug=debug, log_level=log_level,
tests/server/fastmcp/test_server.py+47 −0 modified@@ -12,6 +12,7 @@ from mcp.server.fastmcp.resources import FileResource, FunctionResource from mcp.server.fastmcp.utilities.types import Audio, Image from mcp.server.session import ServerSession +from mcp.server.transport_security import TransportSecuritySettings from mcp.shared.exceptions import McpError from mcp.shared.memory import ( create_connected_server_and_client_session as client_session, @@ -183,6 +184,52 @@ def get_data(x: str) -> str: # pragma: no cover return f"Data: {x}" +class TestDnsRebindingProtection: + """Tests for automatic DNS rebinding protection on localhost.""" + + def test_auto_enabled_for_127_0_0_1(self): + """DNS rebinding protection should auto-enable for host=127.0.0.1.""" + mcp = FastMCP(host="127.0.0.1") + assert mcp.settings.transport_security is not None + assert mcp.settings.transport_security.enable_dns_rebinding_protection is True + assert "127.0.0.1:*" in mcp.settings.transport_security.allowed_hosts + assert "localhost:*" in mcp.settings.transport_security.allowed_hosts + assert "http://127.0.0.1:*" in mcp.settings.transport_security.allowed_origins + assert "http://localhost:*" in mcp.settings.transport_security.allowed_origins + + def test_auto_enabled_for_localhost(self): + """DNS rebinding protection should auto-enable for host=localhost.""" + mcp = FastMCP(host="localhost") + assert mcp.settings.transport_security is not None + assert mcp.settings.transport_security.enable_dns_rebinding_protection is True + assert "127.0.0.1:*" in mcp.settings.transport_security.allowed_hosts + assert "localhost:*" in mcp.settings.transport_security.allowed_hosts + + def test_auto_enabled_for_ipv6_localhost(self): + """DNS rebinding protection should auto-enable for host=::1 (IPv6 localhost).""" + mcp = FastMCP(host="::1") + assert mcp.settings.transport_security is not None + assert mcp.settings.transport_security.enable_dns_rebinding_protection is True + assert "[::1]:*" in mcp.settings.transport_security.allowed_hosts + assert "http://[::1]:*" in mcp.settings.transport_security.allowed_origins + + def test_not_auto_enabled_for_other_hosts(self): + """DNS rebinding protection should NOT auto-enable for other hosts.""" + mcp = FastMCP(host="0.0.0.0") + assert mcp.settings.transport_security is None + + def test_explicit_settings_not_overridden(self): + """Explicit transport_security settings should not be overridden.""" + custom_settings = TransportSecuritySettings( + enable_dns_rebinding_protection=False, + ) + mcp = FastMCP(host="127.0.0.1", transport_security=custom_settings) + # Settings are copied by pydantic, so check values not identity + assert mcp.settings.transport_security is not None + assert mcp.settings.transport_security.enable_dns_rebinding_protection is False + assert mcp.settings.transport_security.allowed_hosts == [] + + def tool_fn(x: int, y: int) -> int: return x + y
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-9h52-p55h-vw2fghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-66416ghsaADVISORY
- github.com/modelcontextprotocol/python-sdk/commit/d3a184119e4479ea6a63590bc41f01dc06e3fa99ghsax_refsource_MISCWEB
- github.com/modelcontextprotocol/python-sdk/security/advisories/GHSA-9h52-p55h-vw2fghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.