Skip to content

Security: DNS rebinding protection is opt-in, not enabled by default #3784

Open

Description

@alemaiorano

Security Configuration Recommendation

The TransportSecurityMiddleware in mcp/server/transport_security.py has DNS rebinding protection available but disabled by default:

self.settings = settings or TransportSecuritySettings(enable_dns_rebinding_protection=False)

Every deployment that does not explicitly pass TransportSecuritySettings(enable_dns_rebinding_protection=True, allowed_hosts=[...]) is vulnerable to DNS rebinding attacks.

Impact

DNS rebinding bypasses same-origin policy and allows malicious webpages to interact with local MCP servers. Most MCP servers run on localhost during development.

Recommendation

  1. Enable DNS rebinding protection by default
  2. Or at minimum: log a warning when disabled
  3. Document the risk prominently
  4. Consider a strict mode that enables all protections

Reference

Same class as GHSA-9h52-p55h-vw2f. Similar to TypeScript SDK maxToolInputElements being off by default (GHSA-46jr).

Verified in mcp 1.29.0 and 2.2.0 source.

Activity

  1. added
    enhancementRequest for a new feature that's not currently supported
    on Oct 28, 2026
  2. sattyamjjain commented on Oct 29, 2026

    @sattyamjjain

    I checked this against main (d7845c0), and the default is narrower than the title suggests.

    • TransportSecuritySettings.enable_dns_rebinding_protection defaults to True (src/mcp/server/transport_security.py L26).
    • The middleware's fallback, when it gets no settings, turns it off: TransportSecuritySettings(enable_dns_rebinding_protection=False) (L47-48).
    • But streamable_http_app in src/mcp/server/lowlevel/server.py (L752-757) and MCPServer.sse_app (src/mcp/server/mcpserver/server.py L1163-1168) auto-enable it when host is 127.0.0.1, localhost or ::1 and no transport_security is passed.

    So the exposed cases are servers that build SseServerTransport or StreamableHTTPSessionManager directly without settings, and servers bound to a non-loopback host such as 0.0.0.0 without transport_security. Also, a request with no Origin header passes _validate_origin (L74-76).

    The spec (2025-11-25, basic/transports) says "Servers MUST validate the Origin header on all incoming connections to prevent DNS rebinding attacks". A middle ground could be to keep the loopback auto-enabled and log a warning, or refuse to start when the host is non-loopback and no settings were passed.

    I only read main, not the 1.29.0 tag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementRequest for a new feature that's not currently supported

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions