Skip to content

Commit 0382c32

Browse files
committed
fix: validate wildcard port allowlist suffixes
1 parent ac96f88 commit 0382c32

2 files changed

Lines changed: 8 additions & 4 deletions

File tree

src/mcp/server/transport_security.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ def _validate_host(self, host: str | None) -> bool:
5555
if allowed.endswith(":*"):
5656
# Extract base host from pattern
5757
base_host = allowed[:-2]
58-
# Check if the actual host starts with base host and has a port
59-
if host.startswith(base_host + ":"):
58+
# Check if the actual host is base host plus a numeric port.
59+
if host.startswith(base_host + ":") and host[len(base_host) + 1 :].isdigit():
6060
return True
6161

6262
logger.warning(f"Invalid Host header: {host}")
@@ -77,8 +77,8 @@ def _validate_origin(self, origin: str | None) -> bool:
7777
if allowed.endswith(":*"):
7878
# Extract base origin from pattern
7979
base_origin = allowed[:-2]
80-
# Check if the actual origin starts with base origin and has a port
81-
if origin.startswith(base_origin + ":"):
80+
# Check if the actual origin is base origin plus a numeric port.
81+
if origin.startswith(base_origin + ":") and origin[len(base_origin) + 1 :].isdigit():
8282
return True
8383

8484
logger.warning(f"Invalid Origin header: {origin}")

tests/server/test_transport_security.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,14 @@ def _request(host: str | None, origin: str | None, content_type: str | None = "a
3131
pytest.param(None, None, 421, id="missing-host"),
3232
pytest.param("evil.example", None, 421, id="host-no-match"),
3333
pytest.param("evil.example:9000", None, 421, id="host-wildcard-base-mismatch"),
34+
pytest.param("wild.example:9000.evil", None, 421, id="host-wildcard-port-suffix"),
35+
pytest.param("wild.example:notaport", None, 421, id="host-wildcard-nonnumeric-port"),
3436
pytest.param("good.example", None, None, id="host-exact-no-origin"),
3537
pytest.param("wild.example:9000", None, None, id="host-wildcard-match"),
3638
pytest.param("good.example", "http://evil.example", 403, id="origin-no-match"),
3739
pytest.param("good.example", "http://evil.example:9000", 403, id="origin-wildcard-base-mismatch"),
40+
pytest.param("good.example", "http://wild.example:9000.evil", 403, id="origin-wildcard-port-suffix"),
41+
pytest.param("good.example", "http://wild.example:notaport", 403, id="origin-wildcard-nonnumeric-port"),
3842
pytest.param("good.example", "http://good.example", None, id="origin-exact"),
3943
pytest.param("good.example", "http://wild.example:9000", None, id="origin-wildcard-match"),
4044
],

0 commit comments

Comments
 (0)