diff -Nru jupyter-notebook-5.2.2/debian/changelog jupyter-notebook-5.2.2/debian/changelog --- jupyter-notebook-5.2.2/debian/changelog 2017-12-06 21:25:37.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/changelog 2022-08-28 22:00:01.000000000 +0000 @@ -1,3 +1,45 @@ +jupyter-notebook (5.2.2-1ubuntu0.1) bionic-security; urgency=medium + + * SECURITY UPDATE: Cross-site scripting via untrusted notebook (LP: #1982670) + - debian/patches/CVE-2018-19351.patch: Apply CSP sandboxing to nbconvert + responses. + - CVE-2018-19351 + * SECURITY UPDATE: Cross-site inclusion on malicious pages (LP: #1982670) + - debian/patches/CVE-2019-9644-1.patch: Block cross-origin GET and HEAD + requests with mismatched Referer. + - debian/patches/CVE-2019-9644-2.patch: Add CSRF checks on files endpoints. + - debian/patches/CVE-2019-9644-3.patch: Set X-Content-Type-Options: nosniff + on all handlers for protecting non-script resources. + - CVE-2019-9644 + * SECURITY UPDATE: Crafted link to login page redirects to malicious site + (LP: #1982670) + - debian/patches/CVE-2019-10255-1.patch: Parse URLs when validating redirect + targets. + - debian/patches/CVE-2019-10255-2.patch: Protect against Chrome mishandling + backslashes as slashes in URLs. + - debian/patches/CVE-2019-10255-3.patch: Handle empty netloc being + interpreted as first path part being the netloc by buggy browsers. + - CVE-2019-10255, CVE-2019-10856 + * SECURITY UPDATE: Cross-site scripting (LP: #1982670) + - debian/patches/CVE-2018-21030-1.patch: Use CSP header to treat served + files as belonging to a separate origin. + - debian/patches/CVE-2018-21030-2.patch: Add a content_security_policy + property instead of the CSP header. + - CVE-2018-21030 + * SECURITY UPDATE: Crafted link to login page redirects to spoofed server + (LP: #1982670) + - debian/patches/CVE-2020-26215.patch: Validate redirect target in + TrailingSlashHandler. + - CVE-2020-26215 + * SECURITY UPDATE: Sensitive information disclosure leading to unauthorized + access (LP: #1982670) + - debian/patches/CVE-2022-24758.patch: Log only a non-sensitive subset of + the headers when a HTTP 5xx error other than HTTP 502 is triggered. + - CVE-2022-24758 + * Address Lintian warnings. + + -- Luís Infante da Câmara Sun, 28 Aug 2022 23:00:01 +0100 + jupyter-notebook (5.2.2-1) unstable; urgency=medium * New upstream release. diff -Nru jupyter-notebook-5.2.2/debian/control jupyter-notebook-5.2.2/debian/control --- jupyter-notebook-5.2.2/debian/control 2017-12-06 21:25:37.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/control 2022-08-28 22:00:01.000000000 +0000 @@ -1,12 +1,13 @@ Source: jupyter-notebook -Maintainer: Debian Python Modules Team +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Debian Python Modules Team Uploaders: Gordon Ball , Jerome Benoit Section: python Priority: optional Standards-Version: 4.1.1 Homepage: https://github.com/jupyter/notebook -Vcs-Git: https://anonscm.debian.org/git/python-modules/packages/jupyter-notebook.git -Vcs-Browser: https://anonscm.debian.org/git/python-modules/packages/jupyter-notebook.git +Vcs-Git: https://salsa.debian.org/python-team/packages/jupyter-notebook.git +Vcs-Browser: https://salsa.debian.org/python-team/packages/jupyter-notebook Build-Depends: debhelper (>= 10), dh-python, python3-all, diff -Nru jupyter-notebook-5.2.2/debian/patches/CVE-2018-19351.patch jupyter-notebook-5.2.2/debian/patches/CVE-2018-19351.patch --- jupyter-notebook-5.2.2/debian/patches/CVE-2018-19351.patch 1970-01-01 00:00:00.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/CVE-2018-19351.patch 2022-08-28 22:00:01.000000000 +0000 @@ -0,0 +1,46 @@ +From 107a89fce5f413fb5728c1c5d2c7788e1fb17491 Mon Sep 17 00:00:00 2001 +From: Thomas Kluyver +Date: Mon, 22 Oct 2018 14:52:36 +0100 +Subject: [PATCH] Apply CSP sandboxing for nbconvert responses + +These may contain untrusted content, so they should be treated as being +from a different domain to the notebook server. +--- + notebook/nbconvert/handlers.py | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/notebook/nbconvert/handlers.py b/notebook/nbconvert/handlers.py +index bb26664aa..bf0a4bfba 100644 +--- a/notebook/nbconvert/handlers.py ++++ b/notebook/nbconvert/handlers.py +@@ -78,6 +78,13 @@ class NbconvertFileHandler(IPythonHandler): + + SUPPORTED_METHODS = ('GET',) + ++ @property ++ def content_security_policy(self): ++ # In case we're serving HTML/SVG, confine any Javascript to a unique ++ # origin so it can't interact with the notebook server. ++ return super(NbconvertFileHandler, self).content_security_policy + \ ++ "; sandbox allow-scripts" ++ + @web.authenticated + def get(self, format, path): + +@@ -145,6 +152,13 @@ class NbconvertFileHandler(IPythonHandler): + class NbconvertPostHandler(IPythonHandler): + SUPPORTED_METHODS = ('POST',) + ++ @property ++ def content_security_policy(self): ++ # In case we're serving HTML/SVG, confine any Javascript to a unique ++ # origin so it can't interact with the notebook server. ++ return super(NbconvertPostHandler, self).content_security_policy + \ ++ "; sandbox allow-scripts" ++ + @web.authenticated + def post(self, format): + exporter = get_exporter(format, config=self.config) +-- +2.17.1 + diff -Nru jupyter-notebook-5.2.2/debian/patches/CVE-2018-21030-1.patch jupyter-notebook-5.2.2/debian/patches/CVE-2018-21030-1.patch --- jupyter-notebook-5.2.2/debian/patches/CVE-2018-21030-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/CVE-2018-21030-1.patch 2022-08-28 22:00:01.000000000 +0000 @@ -0,0 +1,44 @@ +From 901f1e9492f70ff0c32e45dd5788f11d4aeb7da3 Mon Sep 17 00:00:00 2001 +From: Thomas Kluyver +Date: Thu, 15 Feb 2018 14:02:46 +0000 +Subject: [PATCH 1/2] Use CSP header to treat served files as belonging to a + separate origin + +--- + notebook/base/handlers.py | 4 ++++ + notebook/files/handlers.py | 4 ++++ + 2 files changed, 8 insertions(+) + +diff --git a/notebook/base/handlers.py b/notebook/base/handlers.py +index ddd82426d..d1f5afc4a 100755 +--- a/notebook/base/handlers.py ++++ b/notebook/base/handlers.py +@@ -629,6 +629,10 @@ class AuthenticatedFileHandler(IPythonHandler, web.StaticFileHandler): + # disable browser caching, rely on 304 replies for savings + if "v" not in self.request.arguments: + self.add_header("Cache-Control", "no-cache") ++ ++ # In case we're serving HTML/SVG, confine any Javascript to a unique ++ # origin so it can't interact with the notebook server. ++ self.set_header('Content-Security-Policy', 'sandbox allow-scripts') + + def compute_etag(self): + return None +diff --git a/notebook/files/handlers.py b/notebook/files/handlers.py +index b94214984..2cf63ff95 100644 +--- a/notebook/files/handlers.py ++++ b/notebook/files/handlers.py +@@ -64,6 +64,10 @@ class FilesHandler(IPythonHandler): + else: + self.set_header('Content-Type', 'text/plain; charset=UTF-8') + ++ # In case we're serving HTML/SVG, confine any Javascript to a unique ++ # origin so it can't interact with the notebook server. ++ self.set_header('Content-Security-Policy', 'sandbox allow-scripts') ++ + if include_body: + if model['format'] == 'base64': + b64_bytes = model['content'].encode('ascii') +-- +2.17.1 + diff -Nru jupyter-notebook-5.2.2/debian/patches/CVE-2018-21030-2.patch jupyter-notebook-5.2.2/debian/patches/CVE-2018-21030-2.patch --- jupyter-notebook-5.2.2/debian/patches/CVE-2018-21030-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/CVE-2018-21030-2.patch 2022-08-28 22:00:01.000000000 +0000 @@ -0,0 +1,72 @@ +From 694ed72fb4a80ccae6b352811f5dd2277e6889b8 Mon Sep 17 00:00:00 2001 +From: Thomas Kluyver +Date: Thu, 8 Mar 2018 16:59:12 +0000 +Subject: [PATCH 2/2] Use content_security_policy property to add restriction + when serving user files + +--- + notebook/base/handlers.py | 11 +++++++---- + notebook/files/handlers.py | 11 +++++++---- + 2 files changed, 14 insertions(+), 8 deletions(-) + +diff --git a/notebook/base/handlers.py b/notebook/base/handlers.py +index d1f5afc4a..430ff0f0e 100755 +--- a/notebook/base/handlers.py ++++ b/notebook/base/handlers.py +@@ -601,6 +601,13 @@ class Template404(IPythonHandler): + class AuthenticatedFileHandler(IPythonHandler, web.StaticFileHandler): + """static files should only be accessible when logged in""" + ++ @property ++ def content_security_policy(self): ++ # In case we're serving HTML/SVG, confine any Javascript to a unique ++ # origin so it can't interact with the notebook server. ++ return super(AuthenticatedFileHandler, self).content_security_policy + \ ++ "; sandbox allow-scripts" ++ + @web.authenticated + def get(self, path): + if os.path.splitext(path)[1] == '.ipynb' or self.get_argument("download", False): +@@ -629,10 +636,6 @@ class AuthenticatedFileHandler(IPythonHandler, web.StaticFileHandler): + # disable browser caching, rely on 304 replies for savings + if "v" not in self.request.arguments: + self.add_header("Cache-Control", "no-cache") +- +- # In case we're serving HTML/SVG, confine any Javascript to a unique +- # origin so it can't interact with the notebook server. +- self.set_header('Content-Security-Policy', 'sandbox allow-scripts') + + def compute_etag(self): + return None +diff --git a/notebook/files/handlers.py b/notebook/files/handlers.py +index 2cf63ff95..7973fd691 100644 +--- a/notebook/files/handlers.py ++++ b/notebook/files/handlers.py +@@ -26,6 +26,13 @@ class FilesHandler(IPythonHandler): + a subclass of StaticFileHandler. + """ + ++ @property ++ def content_security_policy(self): ++ # In case we're serving HTML/SVG, confine any Javascript to a unique ++ # origin so it can't interact with the notebook server. ++ return super(FilesHandler, self).content_security_policy + \ ++ "; sandbox allow-scripts" ++ + @web.authenticated + def head(self, path): + self.get(path, include_body=False) +@@ -64,10 +71,6 @@ class FilesHandler(IPythonHandler): + else: + self.set_header('Content-Type', 'text/plain; charset=UTF-8') + +- # In case we're serving HTML/SVG, confine any Javascript to a unique +- # origin so it can't interact with the notebook server. +- self.set_header('Content-Security-Policy', 'sandbox allow-scripts') +- + if include_body: + if model['format'] == 'base64': + b64_bytes = model['content'].encode('ascii') +-- +2.17.1 + diff -Nru jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-1.patch jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-1.patch --- jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-1.patch 2022-08-28 22:00:01.000000000 +0000 @@ -0,0 +1,92 @@ +From 70fe9f0ddb3023162ece21fbb77d5564306b913b Mon Sep 17 00:00:00 2001 +From: Min RK +Date: Wed, 27 Mar 2019 15:41:49 +0100 +Subject: [PATCH] parse urls when validating redirect targets + +simplifies check for redirects to external hosts +--- + notebook/auth/login.py | 7 +++-- + notebook/auth/tests/test_login.py | 48 +++++++++++++++++++++++++++++++ + 2 files changed, 52 insertions(+), 3 deletions(-) + create mode 100644 notebook/auth/tests/test_login.py + +diff --git a/notebook/auth/login.py b/notebook/auth/login.py +index b32123faf..d8289d732 100644 +--- a/notebook/auth/login.py ++++ b/notebook/auth/login.py +@@ -39,14 +39,15 @@ class LoginHandler(IPythonHandler): + """ + 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: +diff --git a/notebook/auth/tests/test_login.py b/notebook/auth/tests/test_login.py +new file mode 100644 +index 000000000..2b5574204 +--- /dev/null ++++ b/notebook/auth/tests/test_login.py +@@ -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) +-- +2.17.1 + diff -Nru jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-2.patch jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-2.patch --- jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-2.patch 2022-08-28 22:00:01.000000000 +0000 @@ -0,0 +1,27 @@ +From 08c4c898182edbe97aadef1815cce50448f975cb Mon Sep 17 00:00:00 2001 +From: Min RK +Date: Wed, 27 Mar 2019 21:43:40 +0100 +Subject: [PATCH] protect against chrome mishandling backslash as slash in URLs + +--- + notebook/auth/login.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/notebook/auth/login.py b/notebook/auth/login.py +index d8289d732..8dbd6112f 100644 +--- a/notebook/auth/login.py ++++ b/notebook/auth/login.py +@@ -39,6 +39,10 @@ class LoginHandler(IPythonHandler): + """ + 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 +-- +2.17.1 + diff -Nru jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-3.patch jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-3.patch --- jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/CVE-2019-10255-3.patch 2022-08-28 22:00:01.000000000 +0000 @@ -0,0 +1,84 @@ +This patch was backported to the version in Ubuntu 18.04. + +From 979e0bd15e794ceb00cc63737fcd5fd9addc4a99 Mon Sep 17 00:00:00 2001 +From: Min RK +Date: Mon, 1 Apr 2019 11:41:52 +0200 +Subject: [PATCH] even more careful with login redirect checks + +handle empty netloc being interpreted as first path part being the netloc by unhelpful browsers +--- + notebook/auth/login.py | 13 ++++++++----- + notebook/auth/tests/test_login.py | 10 ++++++++-- + 2 files changed, 16 insertions(+), 7 deletions(-) + +diff --git a/notebook/auth/login.py b/notebook/auth/login.py +index 8dbd6112f..32c94c37c 100644 +--- a/notebook/auth/login.py ++++ b/notebook/auth/login.py +@@ -6,9 +6,9 @@ + import re + + try: +- from urllib.parse import urlparse # Py 3 ++ from urllib.parse import urlparse, urlunparse # Py 3 + except ImportError: +- from urlparse import urlparse # Py 2 ++ from urlparse import urlparse, urlunparse # Py 2 + import uuid + + from tornado.escape import url_escape +@@ -43,15 +43,18 @@ class LoginHandler(IPythonHandler): + # 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): ++ path_only = urlunparse(parsed._replace(netloc='', scheme='')) ++ if url != path_only 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 url != path_only: + # if full URL, run our cross-origin check: + origin = '%s://%s' % (parsed.scheme, parsed.netloc) + origin = origin.lower() +- if self.allow_origin: ++ if origin == '%s://%s' % (self.request.protocol, self.request.host): ++ allow = True ++ elif self.allow_origin: + allow = self.allow_origin == origin + elif self.allow_origin_pat: + allow = bool(self.allow_origin_pat.match(origin)) +diff --git a/notebook/auth/tests/test_login.py b/notebook/auth/tests/test_login.py +index 2b5574204..9120b539d 100644 +--- a/notebook/auth/tests/test_login.py ++++ b/notebook/auth/tests/test_login.py +@@ -31,6 +31,8 @@ class LoginTest(NotebookTestBase): + "//host" + self.url_prefix + "tree", + "https://google.com", + "/absolute/not/base_url", ++ "///jupyter.org", ++ "/\\some-host", + ): + url = self.login(next=bad_next) + self.assertEqual(url, self.url_prefix) +@@ -39,10 +41,14 @@ class LoginTest(NotebookTestBase): + def test_next_ok(self): + for next_path in ( + "tree/", +- "//" + self.url_prefix + "tree", ++ self.base_url() + "has/host", + "notebooks/notebook.ipynb", + "tree//something", + ): +- expected = self.url_prefix + next_path ++ if "://" in next_path: ++ expected = next_path ++ else: ++ expected = self.url_prefix + next_path ++ + actual = self.login(next=expected) + self.assertEqual(actual, expected) +-- +2.17.1 + diff -Nru jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-1.patch jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-1.patch --- jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-1.patch 1970-01-01 00:00:00.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-1.patch 2022-08-28 22:00:01.000000000 +0000 @@ -0,0 +1,92 @@ +This patch was backported to the version in Ubuntu 18.04. + +From bfaa61385729ed4fb453863053f9a79141f01119 Mon Sep 17 00:00:00 2001 +From: Min RK +Date: Thu, 31 Jan 2019 15:54:50 +0100 +Subject: [PATCH] Block cross-origin GET,HEAD requests with mismatched Referer + +- /files/ downloads must come from a local page (no direct visits or external links) +- same for /api/ requests +- disabling xsrf checks +--- + notebook/base/handlers.py | 58 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 57 insertions(+), 1 deletion(-) + +diff --git a/notebook/base/handlers.py b/notebook/base/handlers.py +index b458445b1..cd801c9a1 100755 +--- a/notebook/base/handlers.py ++++ b/notebook/base/handlers.py +@@ -404,13 +404,69 @@ class IPythonHandler(AuthenticatedHandler): + ) + return allow + ++ def check_referer(self): ++ """Check Referer for cross-site requests. ++ ++ Disables requests to certain endpoints with ++ external or missing Referer. ++ ++ If set, allow_origin settings are applied to the Referer ++ to whitelist specific cross-origin sites. ++ ++ Used on GET for api endpoints and /files/ ++ to block cross-site inclusion (XSSI). ++ """ ++ host = self.request.headers.get("Host") ++ referer = self.request.headers.get("Referer") ++ ++ if not host: ++ self.log.warning("Blocking request with no host") ++ return False ++ if not referer: ++ self.log.warning("Blocking request with no referer") ++ return False ++ ++ referer_url = urlparse(referer) ++ referer_host = referer_url.netloc ++ if referer_host == host: ++ return True ++ ++ # apply cross-origin checks to Referer: ++ origin = "{}://{}".format(referer_url.scheme, referer_url.netloc) ++ if self.allow_origin: ++ allow = self.allow_origin == origin ++ elif self.allow_origin_pat: ++ allow = bool(self.allow_origin_pat.match(origin)) ++ else: ++ # No CORS settings, deny the request ++ allow = False ++ ++ if not allow: ++ self.log.warning("Blocking Cross Origin request for %s. Referer: %s, Host: %s", ++ self.request.path, origin, host, ++ ) ++ return allow ++ + def check_xsrf_cookie(self): + """Bypass xsrf cookie checks when token-authenticated""" + if self.token_authenticated or self.settings.get('disable_check_xsrf', False): + # Token-authenticated requests do not need additional XSRF-check + # Servers without authentication are vulnerable to XSRF + return +- return super(IPythonHandler, self).check_xsrf_cookie() ++ try: ++ return super(IPythonHandler, self).check_xsrf_cookie() ++ except web.HTTPError as e: ++ if self.request.method in {'GET', 'HEAD'}: ++ # Consider Referer a sufficient cross-origin check for GET requests ++ if not self.check_referer(): ++ referer = self.request.headers.get('Referer') ++ if referer: ++ msg = "Blocking Cross Origin request from {}.".format(referer) ++ else: ++ msg = "Blocking request from unknown origin" ++ raise web.HTTPError(403, msg) ++ else: ++ raise + + #--------------------------------------------------------------- + # template rendering +-- +2.17.1 + diff -Nru jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-2.patch jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-2.patch --- jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-2.patch 1970-01-01 00:00:00.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-2.patch 2022-08-28 22:00:01.000000000 +0000 @@ -0,0 +1,74 @@ +This patch was backported to the version in Ubuntu 18.04. + +From b5105814fc41c6d789b317fa59f786bad7f9d798 Mon Sep 17 00:00:00 2001 +From: Min RK +Date: Fri, 18 Jan 2019 12:32:40 +0100 +Subject: [PATCH] add xsrf checks on files endpoints + +--- + notebook/base/handlers.py | 9 ++++++++- + notebook/files/handlers.py | 5 ++++- + notebook/services/nbconvert/handlers.py | 1 + + 3 files changed, 13 insertions(+), 2 deletions(-) + +diff --git a/notebook/base/handlers.py b/notebook/base/handlers.py +index cac040f06..b458445b1 100755 +--- a/notebook/base/handlers.py ++++ b/notebook/base/handlers.py +@@ -596,14 +596,21 @@ class AuthenticatedFileHandler(IPythonHandler, web.StaticFileHandler): + return super(AuthenticatedFileHandler, self).content_security_policy + \ + "; sandbox allow-scripts" + ++ @web.authenticated ++ def head(self, path): ++ self.check_xsrf_cookie() ++ return super(AuthenticatedFileHandler, self).head(path) ++ + @web.authenticated + def get(self, path): ++ self.check_xsrf_cookie() ++ + if os.path.splitext(path)[1] == '.ipynb' or self.get_argument("download", False): + name = path.rsplit('/', 1)[-1] + self.set_attachment_header(name) + + return web.StaticFileHandler.get(self, path) +- ++ + def get_content_type(self): + path = self.absolute_path.strip('/') + if '/' in path: +diff --git a/notebook/files/handlers.py b/notebook/files/handlers.py +index 7973fd691..f679a0b23 100644 +--- a/notebook/files/handlers.py ++++ b/notebook/files/handlers.py +@@ -35,10 +35,13 @@ class FilesHandler(IPythonHandler): + + @web.authenticated + def head(self, path): +- self.get(path, include_body=False) ++ self.check_xsrf_cookie() ++ return self.get(path, include_body=False) + + @web.authenticated + def get(self, path, include_body=True): ++ # /files/ requests must originate from the same site ++ self.check_xsrf_cookie() + cm = self.contents_manager + + if cm.is_hidden(path): +diff --git a/notebook/services/nbconvert/handlers.py b/notebook/services/nbconvert/handlers.py +index 63e731238..2a9897fc4 100644 +--- a/notebook/services/nbconvert/handlers.py ++++ b/notebook/services/nbconvert/handlers.py +@@ -8,6 +8,7 @@ class NbconvertRootHandler(APIHandler): + + @web.authenticated + def get(self): ++ self.check_xsrf_cookie() + try: + from nbconvert.exporters.export import exporter_map + except ImportError as e: +-- +2.17.1 + diff -Nru jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-3.patch jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-3.patch --- jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-3.patch 1970-01-01 00:00:00.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/CVE-2019-9644-3.patch 2022-08-28 22:00:01.000000000 +0000 @@ -0,0 +1,25 @@ +From cfc335b76466ccf1538ce545b654b29b5ab0097c Mon Sep 17 00:00:00 2001 +From: Min RK +Date: Fri, 18 Jan 2019 10:45:50 +0100 +Subject: [PATCH] Set X-Content-Options: nosniff on all handlers + +for XSSI protections of non-script content +--- + notebook/base/handlers.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/notebook/base/handlers.py b/notebook/base/handlers.py +index c5fd8be58..cac040f06 100755 +--- a/notebook/base/handlers.py ++++ b/notebook/base/handlers.py +@@ -82,6 +82,7 @@ class AuthenticatedHandler(web.RequestHandler): + + def set_default_headers(self): + headers = {} ++ headers["X-Content-Type-Options"] = "nosniff" + headers.update(self.settings.get('headers', {})) + + headers["Content-Security-Policy"] = self.content_security_policy +-- +2.17.1 + diff -Nru jupyter-notebook-5.2.2/debian/patches/CVE-2020-26215.patch jupyter-notebook-5.2.2/debian/patches/CVE-2020-26215.patch --- jupyter-notebook-5.2.2/debian/patches/CVE-2020-26215.patch 1970-01-01 00:00:00.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/CVE-2020-26215.patch 2022-08-28 22:00:01.000000000 +0000 @@ -0,0 +1,76 @@ +This patch was backported to the version in Ubuntu 18.04. + +From 2e1c56b0c4a903606d4a2eb13e32409296b9799d Mon Sep 17 00:00:00 2001 +From: Min RK +Date: Thu, 15 Oct 2020 09:39:44 +0200 +Subject: [PATCH] Validate redirect target in TrailingSlashHandler + +Fixes open redirect vulnerability GHSA-c7vm-f5p4-8fqh +--- + notebook/base/handlers.py | 14 ++++++++++---- + notebook/tests/test_paths.py | 18 ++++++++++++++++++ + 2 files changed, 28 insertions(+), 4 deletions(-) + +diff --git a/notebook/base/handlers.py b/notebook/base/handlers.py +index 743f7bac7..5e9210400 100755 +--- a/notebook/base/handlers.py ++++ b/notebook/base/handlers.py +@@ -748,13 +748,19 @@ class APIVersionHandler(APIHandler): + + class TrailingSlashHandler(web.RequestHandler): + """Simple redirect handler that strips trailing slashes +- ++ + This should be the first, highest priority handler. + """ +- ++ + def get(self): +- self.redirect(self.request.uri.rstrip('/')) +- ++ components = self.request.uri.partition("?") ++ rest = components[1:] ++ # trim trailing *and* leading / ++ # to avoid misinterpreting repeated '//' ++ path = "/" + components[0].strip("/") ++ new_uri = "".join([path] + list(rest)) ++ self.redirect(new_uri) ++ + post = put = get + + +diff --git a/notebook/tests/test_paths.py b/notebook/tests/test_paths.py +index f49303a1d..c4f751786 100644 +--- a/notebook/tests/test_paths.py ++++ b/notebook/tests/test_paths.py +@@ -3,6 +3,8 @@ import re + import nose.tools as nt + + from notebook.base.handlers import path_regex ++from notebook.utils import url_path_join ++from .launchnotebook import NotebookTestBase + + try: # py3 + assert_regex = nt.assert_regex +@@ -38,3 +41,18 @@ def test_path_regex_bad(): + '/y/x/foo', + ): + assert_not_regex(path, path_pat) ++ ++ ++class RedirectTestCase(NotebookTestBase): ++ def test_trailing_slash(self): ++ for uri, expected in ( ++ ("/notebooks/mynotebook/", "/notebooks/mynotebook"), ++ ("////foo///", "/foo"), ++ ("//example.com/", "/example.com"), ++ ("/has/param/?hasparam=true", "/has/param?hasparam=true"), ++ ): ++ r = self.request("GET", uri, allow_redirects=False) ++ print(uri, expected) ++ assert r.status_code == 302 ++ assert "Location" in r.headers ++ assert r.headers["Location"] == url_path_join(self.url_prefix, expected) +-- +2.17.1 + diff -Nru jupyter-notebook-5.2.2/debian/patches/CVE-2022-24758.patch jupyter-notebook-5.2.2/debian/patches/CVE-2022-24758.patch --- jupyter-notebook-5.2.2/debian/patches/CVE-2022-24758.patch 1970-01-01 00:00:00.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/CVE-2022-24758.patch 2022-08-28 22:00:01.000000000 +0000 @@ -0,0 +1,32 @@ +This patch was backported to the version in Ubuntu 18.04. + +From c219ce43c1ea25123fa70d264e7735bdf4585b1e Mon Sep 17 00:00:00 2001 +From: Steven Silvester +Date: Tue, 15 Mar 2022 10:42:52 -0500 +Subject: [PATCH] Merge pull request from GHSA-m87f-39q9-6f55 + +--- + notebook/log.py | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/notebook/log.py b/notebook/log.py +index eb246bc40..f7e393770 100644 +--- a/notebook/log.py ++++ b/notebook/log.py +@@ -44,7 +44,11 @@ def log_request(handler, log=access_log, log_json=False): + ns['referer'] = request.headers.get('Referer', 'None') + msg = msg + ' referer={referer}' + if status >= 500 and status != 502: +- # log all headers if it caused an error ++ # Log a subset of the headers if it caused an error. ++ headers = {} ++ for header in ['Host', 'Accept', 'Referer', 'User-Agent']: ++ if header in request.headers: ++ headers[header] = request.headers[header] +- log_method(json.dumps(dict(request.headers), indent=2)) ++ log_method(json.dumps(dict(headers), indent=2)) + log_method(msg.format(**ns)) + +-- +2.17.1 + diff -Nru jupyter-notebook-5.2.2/debian/patches/series jupyter-notebook-5.2.2/debian/patches/series --- jupyter-notebook-5.2.2/debian/patches/series 2017-12-06 21:25:37.000000000 +0000 +++ jupyter-notebook-5.2.2/debian/patches/series 2022-08-28 22:00:01.000000000 +0000 @@ -7,3 +7,14 @@ 0007-Debian-specific-hack-to-fix-upstream-s-non-increment.patch 0008-Ignore-errors-in-documentation-notebooks-during-buil.patch 0009-Add-requirejs-shim-for-xterm.patch +CVE-2018-19351.patch +CVE-2018-21030-1.patch +CVE-2018-21030-2.patch +CVE-2019-9644-1.patch +CVE-2019-9644-2.patch +CVE-2019-9644-3.patch +CVE-2019-10255-1.patch +CVE-2019-10255-2.patch +CVE-2019-10255-3.patch +CVE-2020-26215.patch +CVE-2022-24758.patch