Skip to content

Commit 2903625

Browse files
minrkZsailer
andauthored
Merge pull request from GHSA-r726-vmfq-j9j3
Co-authored-by: Zachary Sailer <[email protected]>
1 parent 87a4927 commit 2903625

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

jupyter_server/auth/login.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,25 @@ def _redirect_safe(self, url, default=None):
4141
# \ is not valid in urls, but some browsers treat it as /
4242
# instead of %5C, causing `\\` to behave as `//`
4343
url = url.replace("\\", "%5C")
44+
# urllib and browsers interpret extra '/' in the scheme separator (`scheme:///host/path`)
45+
# differently.
46+
# urllib gives scheme=scheme, netloc='', path='/host/path', while
47+
# browsers get scheme=scheme, netloc='host', path='/path'
48+
# so make sure ':///*' collapses to '://' by splitting and stripping any additional leading slash
49+
# don't allow any kind of `:/` shenanigans by splitting on ':' only
50+
# and replacing `:/*` with exactly `://`
51+
if ":" in url:
52+
scheme, _, rest = url.partition(":")
53+
url = f"{scheme}://{rest.lstrip('/')}"
4454
parsed = urlparse(url)
45-
if parsed.netloc or not (parsed.path + "/").startswith(self.base_url):
55+
# full url may be `//host/path` (empty scheme == same scheme as request)
56+
# or `https://host/path`
57+
# or even `https:///host/path` (invalid, but accepted and ambiguously interpreted)
58+
if (parsed.scheme or parsed.netloc) or not (parsed.path + "/").startswith(self.base_url):
4659
# require that next_url be absolute path within our path
4760
allow = False
4861
# OR pass our cross-origin check
49-
if parsed.netloc:
62+
if parsed.scheme or parsed.netloc:
5063
# if full URL, run our cross-origin check:
5164
origin = f"{parsed.scheme}://{parsed.netloc}"
5265
origin = origin.lower()

tests/auth/test_login.py

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ def login(jp_serverapp, http_server_client, jp_base_url, login_headers):
9292
"//host{base_url}tree",
9393
"https://google.com",
9494
"/absolute/not/base_url",
95+
"https:///a%40b/extra/slash",
9596
),
9697
)
9798
async def test_next_bad(login, jp_base_url, bad_next):

0 commit comments

Comments
 (0)