CVE-2019-10255
Description
An Open Redirect vulnerability for all browsers in Jupyter Notebook before 5.7.7 and some browsers (Chrome, Firefox) in JupyterHub before 0.9.5 allows crafted links to the login page, which will redirect to a malicious site after successful login. Servers running on a base_url prefix are not affected.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Open redirect in Jupyter Notebook <5.7.7 and JupyterHub <0.9.5 allows attackers to redirect users to malicious sites after login via crafted login links.
Vulnerability
An open redirect vulnerability exists in the login page of Jupyter Notebook versions prior to 5.7.7 and JupyterHub versions prior to 0.9.5 [1]. The bug resides in the _redirect_safe function in notebook/auth/login.py, which fails to properly validate redirect targets against the server's base URL when no base_url prefix is configured [4]. The vulnerability affects all browsers for Notebook and Chrome/Firefox for JupyterHub [1].
Exploitation
An attacker can craft a link to the Jupyter login page with a next parameter pointing to an arbitrary external domain. When a user clicks the link and successfully authenticates, the server redirects the user to the attacker-controlled site [1][4]. No prior authentication or special privileges are required; user interaction (clicking the link and logging in) is the only condition [1].
Impact
Upon successful exploitation, the attacker achieves an open redirect, enabling phishing attacks, credential harvesting if the malicious site mimics the login page, or distribution of malware after the user completes login [1]. The redirect occurs after authentication, so the user may already have a valid session, but the redirect itself does not leak session tokens directly [1].
Mitigation
The vulnerability is fixed in Jupyter Notebook version 5.7.7 and JupyterHub version 0.9.5 [1]. Users should upgrade immediately. Additionally, deploying Jupyter or JupyterHub with a non-empty base_url prefix mitigates the issue, as the redirect validation is only bypassed when the base URL is the root path [4]. No other workarounds are provided.
AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
notebookPyPI | < 5.7.8 | 5.7.8 |
jupyterhubPyPI | < 0.9.6 | 0.9.6 |
Affected products
3- ghsa-coords2 versions
< 0.9.6+ 1 more
- (no CPE)range: < 0.9.6
- (no CPE)range: < 5.7.8
Patches
308c4c898182eprotect against chrome mishandling backslash as slash in URLs
1 file changed · +4 −0
notebook/auth/login.py+4 −0 modified@@ -39,6 +39,10 @@ def _redirect_safe(self, url, default=None): """ if default is None: default = self.base_url + # protect chrome users from mishandling unescaped backslashes. + # \ is not valid in urls, but some browsers treat it as / + # instead of %5C, causing `\\` to behave as `//` + url = url.replace("\\", "%5C") parsed = urlparse(url) if parsed.netloc or not (parsed.path + '/').startswith(self.base_url): # require that next_url be absolute path within our path
d65328d48418changelog for redirect check
1 file changed · +2 −2
docs/source/changelog.rst+2 −2 modified@@ -31,21 +31,21 @@ We strongly recommend that you upgrade pip to version 9+ of pip before upgrading - Further improve compatibility with tornado 6 with improved checks for when websockets are closed. - Fix regression in 5.7.6 on Windows where .js files could have the wrong mime-type. +- Fix Open Redirect vulnerability where certain malicious URLs could redirect from the Jupyter login page to a malicious site after a successful login. A CVE has been requested for this vulnerability. .. _release-5.7.6: 5.7.6 ----- -5.7.6 contains a security fix for a cross-site inclusion (XSSI) vulnerability, +5.7.6 contains a security fix for a cross-site inclusion (XSSI) vulnerability (CVE-2019–9644), where files at a known URL could be included in a page from an unauthorized website if the user is logged into a Jupyter server. The fix involves setting the ``X-Content-Type-Options: nosniff`` header, and applying CSRF checks previously on all non-GET API requests to GET requests to API endpoints and the /files/ endpoint. The attacking page is able to access some contents of files when using Internet Explorer through script errors, but this has not been demonstrated with other browsers. -A CVE has been requested for this vulnerability. .. _release-5.7.5:
70fe9f0ddb30parse urls when validating redirect targets
2 files changed · +52 −3
notebook/auth/login.py+4 −3 modified@@ -39,14 +39,15 @@ def _redirect_safe(self, url, default=None): """ if default is None: default = self.base_url - if not url.startswith(self.base_url): + parsed = urlparse(url) + if 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 '://' in url: + if parsed.netloc: # if full URL, run our cross-origin check: - parsed = urlparse(url.lower()) origin = '%s://%s' % (parsed.scheme, parsed.netloc) + origin = origin.lower() if self.allow_origin: allow = self.allow_origin == origin elif self.allow_origin_pat:
notebook/auth/tests/test_login.py+48 −0 added@@ -0,0 +1,48 @@ +"""Tests for login redirects""" + +import requests +from tornado.httputil import url_concat + +from notebook.tests.launchnotebook import NotebookTestBase + + +class LoginTest(NotebookTestBase): + def login(self, next): + first = requests.get(self.base_url() + "login") + first.raise_for_status() + resp = requests.post( + url_concat( + self.base_url() + "login", + {'next': next}, + ), + allow_redirects=False, + data={ + "password": self.token, + "_xsrf": first.cookies.get("_xsrf", ""), + }, + cookies=first.cookies, + ) + resp.raise_for_status() + return resp.headers['Location'] + + def test_next_bad(self): + for bad_next in ( + "//some-host", + "//host" + self.url_prefix + "tree", + "https://google.com", + "/absolute/not/base_url", + ): + url = self.login(next=bad_next) + self.assertEqual(url, self.url_prefix) + assert url + + def test_next_ok(self): + for next_path in ( + "tree/", + "//" + self.url_prefix + "tree", + "notebooks/notebook.ipynb", + "tree//something", + ): + expected = self.url_prefix + next_path + actual = self.login(next=expected) + self.assertEqual(actual, expected)
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
11- github.com/advisories/GHSA-rv62-4pmj-xw6hghsaADVISORY
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/UP5RLEES2JBBNSNLBR65XM6PCD4EMF7D/mitrevendor-advisoryx_refsource_FEDORA
- lists.fedoraproject.org/archives/list/package-announce%40lists.fedoraproject.org/message/VMDPJBVXOVO6LYGAT46VZNHH6JKSCURO/mitrevendor-advisoryx_refsource_FEDORA
- nvd.nist.gov/vuln/detail/CVE-2019-10255ghsaADVISORY
- blog.jupyter.org/open-redirect-vulnerability-in-jupyter-jupyterhub-adf43583f1e4ghsax_refsource_MISCWEB
- github.com/jupyter/notebook/commit/08c4c898182edbe97aadef1815cce50448f975cbghsax_refsource_MISCWEB
- github.com/jupyter/notebook/commit/70fe9f0ddb3023162ece21fbb77d5564306b913bghsax_refsource_MISCWEB
- github.com/jupyter/notebook/commit/d65328d4841892b412aef9015165db1eb029a8edghsax_refsource_MISCWEB
- github.com/jupyter/notebook/compare/05aa4b2...16cf97cghsax_refsource_MISCWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/UP5RLEES2JBBNSNLBR65XM6PCD4EMF7DghsaWEB
- lists.fedoraproject.org/archives/list/package-announce@lists.fedoraproject.org/message/VMDPJBVXOVO6LYGAT46VZNHH6JKSCUROghsaWEB
News mentions
0No linked articles in our index yet.