Repository navigation
web,websocket: Unmerge check_origin methods - #3768
Merged
bdarnell merged 2 commits intoOct 7, 2026
Merged
Conversation
…eck_origin Folding WebSocketHandler.check_origin into RequestHandler (to share it with cross_origin_protection) changed when it is called: it ran in RequestHandler._execute, before prepare(), instead of in WebSocketHandler.get(), after prepare(). Applications such as Jupyter Server override check_origin in ways that depend on prepare() (to exempt token-authenticated requests), and these overrides failed with 500 errors. Because Jupyter defines check_origin on all of its handlers, enabling cross_origin_protection would also have called it before prepare() for every cross-origin POST. The two hooks have different contracts, so give them different names: - RequestHandler.check_trusted_origin is the new hook for cross_origin_protection. It is called before prepare() and must depend only on the request itself. Its default checks the trusted_origins setting. - WebSocketHandler.check_origin is restored and is again called from get() after prepare() (and after the Upgrade/Connection header checks). It keeps the new 6.6 semantics: it is skipped for requests that are same-origin according to Sec-Fetch-Site or the Origin/Host comparison, and its default calls check_trusted_origin. Non-websocket handlers that receive a GET with an Upgrade: websocket header are no longer subject to the origin check, and rejected websocket origins are once again logged at debug level with a "Cross origin websockets not allowed" response body, as in 6.5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P5zJUPT4vE2M6GK7gqHcqo
An override that exempts requests carrying a token must verify the token, or an attacker can add an invalid one to a cross-site request and have it authenticated by the victim's cookies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P5zJUPT4vE2M6GK7gqHcqo
Member
Author
|
@andrii-i (I'm tagging you because you opened #3730) FYI this is not a victory for the new downstream testbed; I just asked claude to look at the changes between |
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.
In an effort to offer a unified
RequestHandler.check_originfor both regular XSRF protection and cross-origin websocket protection, I had changed the semantics of the existingWebSocketHandler.check_originmethod. Among other things, it moved from being called after prepare() to before, but this is backwards-incompatible in ways that break jupyter_server (possibly among others)This PR undoes the merger of the two methods, leaving WebSocketHandler.check_origin to be called after prepare(), and a new pre-prepare hook named
RequestHandler.check_trusted_originto be used for XSRF protection in regular handlers.The behavior of WebSocketHandler.check_origin has still changed in some ways to be closer to the new check_trusted_origin, where the changes seem unlikely to break existing users.
check_originis no longer called at all if other signals such as theSec-Fetch-Siteheader tell us that this is a same-origin request, and its default implementation consults thetrusted_originslist that it shares withcheck_trusted_origin.