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.
What happened
TransportSecurityMiddlewaretreatsallowed_hosts/allowed_originsentries 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.evilwild.example:9000.evilThe same pattern accepts Origin
http://wild.example:9000.evilforhttp://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 meanbaseplus a numeric port, not any string that starts withbase:.How to reproduce
On
main@08a3bc8: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.pyand reproduced it locally.