Skip to content

Commit

Permalink
Merge pull request from GHSA-r726-vmfq-j9j3
Browse files Browse the repository at this point in the history
Co-authored-by: Zachary Sailer <zsailer@apple.com>
  • Loading branch information
minrk and Zsailer authored Aug 18, 2023
1 parent 87a4927 commit 2903625
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 2 deletions.
17 changes: 15 additions & 2 deletions jupyter_server/auth/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,25 @@ def _redirect_safe(self, url, default=None):
# \ is not valid in urls, but some browsers treat it as /
# instead of %5C, causing `\\` to behave as `//`
url = url.replace("\\", "%5C")
# urllib and browsers interpret extra '/' in the scheme separator (`scheme:///host/path`)
# differently.
# urllib gives scheme=scheme, netloc='', path='/host/path', while
# browsers get scheme=scheme, netloc='host', path='/path'
# so make sure ':///*' collapses to '://' by splitting and stripping any additional leading slash
# don't allow any kind of `:/` shenanigans by splitting on ':' only
# and replacing `:/*` with exactly `://`
if ":" in url:
scheme, _, rest = url.partition(":")
url = f"{scheme}://{rest.lstrip('/')}"
parsed = urlparse(url)
if parsed.netloc or not (parsed.path + "/").startswith(self.base_url):
# full url may be `//host/path` (empty scheme == same scheme as request)
# or `https://host/path`
# or even `https:///host/path` (invalid, but accepted and ambiguously interpreted)
if (parsed.scheme or parsed.netloc) or not (parsed.path + "/").startswith(self.base_url):
# require that next_url be absolute path within our path
allow = False
# OR pass our cross-origin check
if parsed.netloc:
if parsed.scheme or parsed.netloc:
# if full URL, run our cross-origin check:
origin = f"{parsed.scheme}://{parsed.netloc}"
origin = origin.lower()
Expand Down
1 change: 1 addition & 0 deletions tests/auth/test_login.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ def login(jp_serverapp, http_server_client, jp_base_url, login_headers):
"//host{base_url}tree",
"https://google.com",
"/absolute/not/base_url",
"https:///a%40b/extra/slash",
),
)
async def test_next_bad(login, jp_base_url, bad_next):
Expand Down

0 comments on commit 2903625

Please sign in to comment.