Skip to content

internal/util: match "localhost" case-insensitively in IsLoopback - #1316

Merged
guglielmo-san merged 1 commit into
modelcontextprotocol:mainfrom
akshita317:util/loopback-case-insensitive
Sep 29, 2026
Merged

guglielmo-san merged 1 commit into
modelcontextprotocol:mainfrom
akshita317:util/loopback-case-insensitive

Conversation

@akshita317

@akshita317 akshita317 commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Host names are case-insensitive (RFC 4343), but IsLoopback compared the
host to "localhost" exactly. net/http keeps the Host header as the client
sent it, so a client configured with http://LocalHost:8080/mcp got 403
"invalid Host header" from a streamable or SSE server listening on
127.0.0.1: the DNS rebinding check took the capitalized name for a
foreign host. The same comparison made oauthex reject an HTTP discovery
URL on LOCALHOST as non-loopback, and made the authorization code
handler classify such a redirect URI as a web one.

Accepting any capitalization does not weaken the rebinding protection.
It rejects requests whose Host names an attacker's domain, and every
spelling of localhost names the local machine.

The new TestIsLoopback cases and the TestStreamableLocalhostProtection
case fail without the change.

Fixes #1319

Host names are case-insensitive (RFC 4343), but IsLoopback compared the
host to "localhost" exactly. net/http keeps the Host header as the client
sent it, so a client configured with http://LocalHost:8080/mcp got 403
"invalid Host header" from a streamable or SSE server listening on
127.0.0.1: the DNS rebinding check took the capitalized name for a
foreign host. The same comparison made oauthex reject an HTTP discovery
URL on LOCALHOST as non-loopback, and made the authorization code
handler classify such a redirect URI as a web one.

Accepting any capitalization does not weaken the rebinding protection.
It rejects requests whose Host names an attacker's domain, and every
spelling of localhost names the local machine.

The new TestIsLoopback cases and the TestStreamableLocalhostProtection
case fail without the change.

Fixes modelcontextprotocol#1319

Signed-off-by: Akshita <110122283+akshita317@users.noreply.github.com>
@akshita317
akshita317 force-pushed the util/loopback-case-insensitive branch from 35e9799 to 08d53dd Compare September 29, 2026 14:05
@guglielmo-san

Copy link
Copy Markdown
Contributor

@akshita317 thank you for the contribution!

@guglielmo-san
guglielmo-san enabled auto-merge (squash) September 29, 2026 15:48
@guglielmo-san
guglielmo-san merged commit bdfc208 into modelcontextprotocol:main Sep 29, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mcp: DNS rebinding protection rejects a Host header of "LocalHost"

2 participants