Skip to content

[Server][Client] Refuse OAuth URLs that hide where their host points - #713

Merged
chr-hertel merged 6 commits into
modelcontextprotocol:mainfrom
chr-hertel:client-auth-loopback-literals
Nov 10, 2026
Merged

chr-hertel merged 6 commits into
modelcontextprotocol:mainfrom
chr-hertel:client-auth-loopback-literals

Conversation

@chr-hertel

Copy link
Copy Markdown
Member

Follow-up to #666: SecureUrl::parse() now refuses hosts that reach this machine or a private network without looking like it - 0.0.0.0, ::, IPv4 within IPv6 ([::ffff:127.0.0.1]) and IPv4 in another form than four decimal numbers (127.1, 2130706433, 0x7f000001). Over plain http they were already refused, but over https they got past the loopback check.

[BC Break] for the server's issuer, jwks_uri and resource and for the URLs a client discovers, both in the CHANGELOG. A DNS name that resolves to loopback is still left to egress control, e.g. NoPrivateNetworkHttpClient.

@chr-hertel chr-hertel added Server Issues & PRs related to the Server component Client Issues & PRs related to the Client component auth Issues and PRs related to Authentication / OAuth labels Nov 9, 2026
@chr-hertel chr-hertel added this to the 0.10.0 milestone Nov 9, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Percent-encoded hosts bypass the loopback restriction because browsers normalize accepted URLs to local addresses, allowing an untrusted authorization server to redirect users to local services.

1 open issue
What changed in this PR

Hardens shared OAuth URL validation for the server and client by rejecting address forms that can conceal local or private-network destinations.

Changes:

  • Rejects unspecified addresses, IPv4 embedded in IPv6, and non-standard IPv4 forms.
  • Adds accepted- and rejected-URL test cases.
  • Documents the compatibility changes and the need for separate DNS-based egress controls.
File Description
tests/​Unit/​Server/​Transport/​Http/​OAuth/​SecureUrlTest.php Adds coverage for allowed hosts and rejected address forms.
src/​Server/​Transport/​Http/​OAuth/​SecureUrl.php Adds host-address validation to OAuth URL parsing.
docs/​client/​authorization.md Explains new rejections and remaining DNS-related risks.
CHANGELOG.md Records server and client compatibility breaks.

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The review identifies no active issues requiring changes to the OAuth URL validation hardening.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@chr-hertel
chr-hertel merged commit bef4c8b into modelcontextprotocol:main Nov 10, 2026
33 checks passed
@chr-hertel
chr-hertel deleted the client-auth-loopback-literals branch November 10, 2026 00:02
@chr-hertel chr-hertel added the breaking change Breaking the Backwards Compatibility Promise label Nov 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auth Issues and PRs related to Authentication / OAuth breaking change Breaking the Backwards Compatibility Promise Client Issues & PRs related to the Client component Server Issues & PRs related to the Server component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants