modelcontextprotocol / modelcontextprotocol/python-sdk

DNS rebinding :* allowlist matches Host/Origin suffixes that are not ports

Open Beginner friendly
#3,463 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

v1 v2
Dominant language
Python
Stars
24.3k
Forks
4k
Avg merge
1d 1h
Merged PRs (30d)
31

Description

What happened

TransportSecurityMiddleware treats allowed_hosts / allowed_origins entries that end in :* as a prefix match: value.startswith(base + ":").

With allowed_hosts=["127.0.0.1:*"] or ["wild.example:*"], these Host values are accepted today:

  • 127.0.0.1:8080.evil
  • wild.example:9000.evil

The same pattern accepts Origin http://wild.example:9000.evil for http://wild.example:*.

Existing tests only cover a numeric port (wild.example:9000). They do not cover a suffix after the port.

What I expected

base:* should mean base plus a numeric port, not any string that starts with base:.

How to reproduce

On main @ 08a3bc8:

from mcp.server.transport_security import TransportSecurityMiddleware, TransportSecuritySettings
from starlette.requests import Request

settings = TransportSecuritySettings(
    enable_dns_rebinding_protection=True,
    allowed_hosts=["wild.example:*"],
    allowed_origins=["http://wild.example:*"],
)
mw = TransportSecurityMiddleware(settings)
req = Request({"type": "http", "method": "GET", "headers": [(b"host", b"wild.example:9000.evil")]})
# validate_request returns None (accept). I expected 421.

I can send a PR that requires the suffix after base: to be digits, plus tests for the suffix cases. Happy to do that if you want it.

Written with AI assistance. I read the matcher next to tests/server/test_transport_security.py and reproduced it locally.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in mcp/server/transport_security.py, where TransportSecurityMiddleware matches allowed_hosts and allowed_origins, then read tests/server/test_transport_security.py. Reproduce the reported suffix cases and compare them with the existing numeric-port coverage. Done means numeric ports remain accepted while values such as wild.example:9000.evil and the matching Origin are rejected.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
security
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.