Conversation
…licit allowlist entries Browsers omit the port from the serialized Origin header when it equals the scheme default (RFC 6454 §6.2), so a deployment that configures allowed_origins = ["https://example.com:443"] never matches the browser-sent "https://example.com" — the raw Option<u16> comparison sees Some(443) vs None and rejects with 403. Resolve the incoming origin's effective port (443 for https/wss, 80 for http/ws) before comparing, so an explicitly configured port accepts both spellings of the same effective port while still rejecting genuinely different ports (8443 etc). The omitted-port entry form keeps its any-port wildcard semantics, which deployments behind multiple TLS terminators rely on; the rustdoc now states both behaviors. Fixes modelcontextprotocol#1268 Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1268.
Problem
origin_is_allowedcompares the configured entry's port against the incoming origin's port as rawOption<u16>:Rust a_port.is_none() || a_port == o_portBrowsers omit the port from the serialized
Originheader when it equals the scheme default (RFC 6454 §6.2), so a portless incoming origin arrives asNone. An explicitly configuredhttps://example.com:443therefore never matches a browser-senthttps://example.com→ 403, even though both denote the same effective port. This bites exactly the deployments that do the more careful thing and pin the port explicitly.Fix
Resolve the incoming origin's effective port before comparing (RFC 6454 §4 — omitted port = scheme default: 443 for https/wss, 80 for http/ws):
Rust a_port.is_none() || a_port == &effective_origin_port(*o_port, o_scheme)The comparison stays per-scheme: an
https://…:443entry still rejectshttp://…(whose implicit port is 80).Deliberately unchanged: an entry with an omitted port keeps its any-port wildcard (configures
scheme+host, any port). #1191 / #1192 left that behavior in place and downstream deployments (e.g. spiceai's runtime, which lists origins portless behind TLS terminators) rely on it. Theallowed_originsrustdoc now documents both behaviors so the distinction is discoverable.Behavior matrix
https://example.com:443https://example.comhttps://example.com:443https://example.com:443https://example.com:443https://example.com:8443https://example.com:443http://example.comhttps://example.com(no port)https://example.com:8443http://example.com:80http://example.comTests
Six new cases in
origin_validation(test_custom_headers.rs) covering the matrix above. Verified red→green: the key test fails on the unfixed predicate and passes with the fix; all 35 tests in the file pass.cargo fmt --checkand clippy clean on the touched files.🤖 Generated with Claude Code