Skip to content

[Tiering] Add conformance tests for localhost DNS rebinding protection #103

@pcarleton

Description

@pcarleton

Summary

Localhost MCP servers without authentication are vulnerable to DNS rebinding attacks. The conformance suite should help developers verify their DNS rebinding protection is working correctly.

Motivation

Many MCP servers run on localhost during development or for local-only use cases, often without authentication. In this configuration, the only protection against malicious websites interacting with the server is Origin header validation.

The attack:

  1. User visits evil.com in their browser
  2. evil.com's JavaScript makes fetch requests to http://localhost:3000/mcp
  3. Browser sends Origin: https://evil.com header
  4. If server doesn't validate Origin, attacker can interact with user's local MCP server
  5. Attacker can invoke tools, read resources, etc.

This conformance test helps developers answer: "Is my localhost server's DNS rebinding protection actually working?"

Scope

These tests are strictly scoped to localhost servers (detected by server URL being localhost, 127.0.0.1, or [::1]). Remote servers with authentication have different security models and are out of scope for this issue.

Suggested Checks

Check: localhost-origin-rebinding-rejected

Spec: "Servers MUST validate the Origin header... If the Origin header is present and invalid, servers MUST respond with HTTP 403 Forbidden."

Send request with Origin: https://attacker.example.com to localhost server → expect HTTP 403.

Check: localhost-origin-valid-accepted

Verify server accepts requests from legitimate localhost origins.

Send request with Origin: http://localhost:PORT → expect normal MCP response (not 403).

Spec Requirements

Keyword Statement
MUST Servers MUST validate the Origin header on all incoming connections to prevent DNS rebinding attacks
MUST If the Origin header is present and invalid, servers MUST respond with HTTP 403 Forbidden
SHOULD When running locally, servers SHOULD bind only to localhost (127.0.0.1) rather than all network interfaces (0.0.0.0)

Implementation Notes

Valid origins for localhost servers:

  • http://localhost / http://localhost:PORT
  • http://127.0.0.1 / http://127.0.0.1:PORT
  • http://[::1] / http://[::1]:PORT (IPv6)

Invalid origins (should 403):

  • Any non-localhost origin (e.g., https://evil.com, https://example.com)

Edge cases to consider:

  • Missing Origin header: Non-browser clients don't send Origin. Servers likely need to accept missing Origin, meaning protection only applies to browser-originated requests.
  • null Origin: Sent by file:// origins. Servers may reasonably accept or reject.

Test activation:

  • Auto-detect: Only run when server URL is localhost/127.0.0.1/[::1]
  • Or explicit flag: --localhost-security

Spec References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions