fix: require every Origin to be allowed on a CORS request - #1262
Open
pjfanning wants to merge 1 commit into
Open
fix: require every Origin to be allowed on a CORS request#1262pjfanning wants to merge 1 commit into
pjfanning wants to merge 1 commit into
Conversation
Motivation: `validateOrigins` accepted a request as soon as *one* of the origins in the `Origin` header matched the allowed matcher, but the response echoes back *every* origin it was given (`CorsSettingsImpl.accessControlAllowOrigin` renders the whole list). A request carrying an allowed origin next to a disallowed one therefore passed validation and echoed the disallowed origin back in `Access-Control-Allow-Origin`. The pre-flight path is not affected because it already only accepts a single origin, so this was limited to simple/actual requests. Modification: Require all origins to match rather than any, keeping the existing `allowed-origins = *` short-circuit. The extra `nonEmpty` guard preserves today's handling of a `null` origin (an empty origin list), which must still be rejected when the allowed origins are restricted - `forall` alone would accept it. Result: An actual request is accepted only when every origin it lists is allowed, so no origin that failed validation is echoed back. A request whose origins are all disallowed is still rejected with `InvalidOrigin` listing them, as before. Tests: - sbt http-cors/test - pass (47 tests); a new test asserts that an actual request listing a disallowed origin next to an allowed one is rejected with `InvalidOrigin`. Verified it fails with the fix stashed (the request is accepted and both origins are echoed). The existing "there are two origins" rejection test and the restricted-`null`-origin test both still pass. - sbt http-cors/mimaReportBinaryIssues - pass References: None - requires all origins of a CORS request to be allowed
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.
Motivation
validateOriginsaccepted a request as soon as one of the origins in theOriginheader matched:but the response echoes back every origin it was given —
CorsSettingsImpl.accessControlAllowOriginrenders the whole list. A request carrying an allowed origin next to a disallowed one therefore passed validation and echoed the disallowed origin back inAccess-Control-Allow-Origin.The pre-flight path is unaffected (it already only accepts a single origin), so this was limited to simple/actual requests. It is not directly browser-exploitable — the Fetch spec sends exactly one
Origin, and a multi-originAccess-Control-Allow-Originis invalid so a browser rejects it — but a value that never passed validation should not be reflected.Modification
Require all origins to match rather than any, keeping the existing
allowed-origins = *short-circuit. The addednonEmptyguard preserves today's handling of anullorigin (an empty origin list), which must still be rejected when the allowed origins are restricted —forallalone would accept it, sinceSeq.empty.forall(_)istrue.Result
An actual request is accepted only when every origin it lists is allowed, so no origin that failed validation is echoed back. A request whose origins are all disallowed is still rejected with
InvalidOriginlisting them, exactly as before.Tests
sbt http-cors/test— pass (47 tests). A new test asserts that an actual request listing a disallowed origin next to an allowed one is rejected withInvalidOrigin. Verified it fails with the fix stashed (the request is accepted and both origins are echoed). The existing "there are two origins" rejection test and the restricted-null-origin test both still pass, which is what pins thenonEmptyguard.sbt http-cors/mimaReportBinaryIssues— pass.scalafmton the changed files — clean.References
None - requires all origins of a CORS request to be allowed
🤖 Generated with Claude Code