diff -Nru python-pip-9.0.1/debian/changelog python-pip-9.0.1/debian/changelog --- python-pip-9.0.1/debian/changelog 2019-04-03 09:23:03.000000000 +0000 +++ python-pip-9.0.1/debian/changelog 2021-04-30 18:11:12.000000000 +0000 @@ -1,3 +1,31 @@ +python-pip (9.0.1-2.3~ubuntu1.18.04.5) bionic; urgency=medium + + * Fix handling of requests exceptions when dependencies are debundled. + (LP: #1833229) + + -- Stefano Rivera Fri, 30 Apr 2021 14:11:12 -0400 + +python-pip (9.0.1-2.3~ubuntu1.18.04.4) bionic-security; urgency=medium + + * SECURITY UPDATE: directory traversal on pip install + - debian/patches/CVE-2019-20916.patch: prevent pip install from + permitting directory traversal + - CVE-2019-20916 + + -- Emilia Torino Thu, 22 Oct 2020 11:40:50 -0300 + +python-pip (9.0.1-2.3~ubuntu1.18.04.3) bionic-security; urgency=medium + + * No change rebuild to pull in security fixes for urllib3 + + -- Marc Deslauriers Fri, 02 Oct 2020 06:59:10 -0400 + +python-pip (9.0.1-2.3~ubuntu1.18.04.2) bionic-security; urgency=medium + + * No change rebuild to pull in security fixes for urllib3 and requests + + -- Mike Salvatore Thu, 13 Aug 2020 19:33:19 -0400 + python-pip (9.0.1-2.3~ubuntu1.18.04.1) bionic; urgency=medium * d/p/bug1822842.patch: Pick fix to resolve issues when using diff -Nru python-pip-9.0.1/debian/patches/CVE-2019-20916.patch python-pip-9.0.1/debian/patches/CVE-2019-20916.patch --- python-pip-9.0.1/debian/patches/CVE-2019-20916.patch 1970-01-01 00:00:00.000000000 +0000 +++ python-pip-9.0.1/debian/patches/CVE-2019-20916.patch 2021-04-30 18:11:12.000000000 +0000 @@ -0,0 +1,44 @@ +--- python-pip-9.0.1.orig/pip/download.py ++++ python-pip-9.0.1/pip/download.py +@@ -824,6 +824,29 @@ def unpack_url(link, location, download_ + write_delete_marker_file(location) + + ++def sanitize_content_filename(filename): ++ # type: (str) -> str ++ """ ++ Sanitize the "filename" value from a Content-Disposition header. ++ """ ++ return os.path.basename(filename) ++ ++ ++def parse_content_disposition(content_disposition, default_filename): ++ # type: (str, str) -> str ++ """ ++ Parse the "filename" value from a Content-Disposition header, and ++ return the default filename if the result is empty. ++ """ ++ _type, params = cgi.parse_header(content_disposition) ++ filename = params.get('filename') ++ if filename: ++ # We need to sanitize the filename to prevent directory traversal ++ # in case the filename contains ".." path parts. ++ filename = sanitize_content_filename(filename) ++ return filename or default_filename ++ ++ + def _download_http_url(link, session, temp_dir, hashes): + """Download link url into temp_dir using provided session""" + target_url = link.url.split('#', 1)[0] +@@ -864,10 +887,7 @@ def _download_http_url(link, session, te + # Have a look at the Content-Disposition header for a better guess + content_disposition = resp.headers.get('content-disposition') + if content_disposition: +- type, params = cgi.parse_header(content_disposition) +- # We use ``or`` here because we don't want to use an "empty" value +- # from the filename param. +- filename = params.get('filename') or filename ++ filename = parse_content_disposition(content_disposition, filename) + ext = splitext(filename)[1] + if not ext: + ext = mimetypes.guess_extension(content_type) diff -Nru python-pip-9.0.1/debian/patches/debundled-requests-exceptions.patch python-pip-9.0.1/debian/patches/debundled-requests-exceptions.patch --- python-pip-9.0.1/debian/patches/debundled-requests-exceptions.patch 1970-01-01 00:00:00.000000000 +0000 +++ python-pip-9.0.1/debian/patches/debundled-requests-exceptions.patch 2021-04-30 18:11:12.000000000 +0000 @@ -0,0 +1,23 @@ +From: Chih-Hsuan Yen +Date: Fri, 30 Apr 2021 14:09:50 -0400 +Subject: Fix handling of requests exceptions when dependencies are debundled. + +Origin: upstream, https://github.com/pypa/pip/pull/6373 +Bug-Upstream: https://github.com/pypa/pip/issues/7486 +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-pip/+bug/1833229 +--- + pip/_vendor/__init__.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/pip/_vendor/__init__.py b/pip/_vendor/__init__.py +index 8e76ab8..d093ffb 100644 +--- a/pip/_vendor/__init__.py ++++ b/pip/_vendor/__init__.py +@@ -77,6 +77,7 @@ if DEBUNDLED: + vendored("progress") + vendored("retrying") + vendored("requests") ++ vendored("requests.exceptions") + vendored("requests.packages") + vendored("requests.packages.urllib3") + vendored("requests.packages.urllib3._collections") diff -Nru python-pip-9.0.1/debian/patches/series python-pip-9.0.1/debian/patches/series --- python-pip-9.0.1/debian/patches/series 2019-04-03 09:22:48.000000000 +0000 +++ python-pip-9.0.1/debian/patches/series 2021-04-30 18:11:12.000000000 +0000 @@ -6,3 +6,6 @@ html5lib-alternative-beta-name.patch use-unvendored-urllib3.diff bug1822842.patch +CVE-2019-20916.patch +debundled-requests-exceptions.patch +skip-vendored-import.patch diff -Nru python-pip-9.0.1/debian/patches/skip-vendored-import.patch python-pip-9.0.1/debian/patches/skip-vendored-import.patch --- python-pip-9.0.1/debian/patches/skip-vendored-import.patch 1970-01-01 00:00:00.000000000 +0000 +++ python-pip-9.0.1/debian/patches/skip-vendored-import.patch 2021-04-30 18:11:12.000000000 +0000 @@ -0,0 +1,72 @@ +From: Chih-Hsuan Yen +Date: Fri, 30 Apr 2021 14:40:29 -0400 +Subject: Ensure all pip._vendor.* modules are mapped to debundled + correspondences (#6113) + +With the original `vendored()` implementation and such an initialization sequence: + +``` +vendored("packaging") +vendored("packaging.version") +``` + +In `sys.modules`, `pip._vendor.packaging` is correctly connected to the debundled `packagi +ng`, while `pip._vendor.packaging.version` is not, as the latter is `__import__`ed from the ex +isting `pip._vendor.packaging` module. That results in the same issue as https://github.com/py +pa/pip/issues/5429 - `pip._vendor.packaging.version.Version` and `packaging.version.Version` c +annot be compared. + +This patch attempts to fix this issue by skipping `__import__` from the vendored name. Thi +s is safe because `vendored()` is called only when `DEBUNDLED = True`, and vendored libraries +are already deleted as per [debundling instructions](https://github.com/pypa/pip/blob/master/s +rc/pip/_vendor/README.rst#debundling). + +Origin: upstream, https://github.com/pypa/pip/pull/6113 +Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-pip/+bug/1833229 +--- + pip/_vendor/__init__.py | 31 ++++++++++++++----------------- + 1 file changed, 14 insertions(+), 17 deletions(-) + +diff --git a/pip/_vendor/__init__.py b/pip/_vendor/__init__.py +index d093ffb..62d8951 100644 +--- a/pip/_vendor/__init__.py ++++ b/pip/_vendor/__init__.py +@@ -30,24 +30,21 @@ def vendored(modulename): + vendored_name = "{0}.{1}".format(__name__, modulename) + + try: +- __import__(vendored_name, globals(), locals(), level=0) ++ __import__(modulename, globals(), locals(), level=0) + except ImportError: +- try: +- __import__(modulename, globals(), locals(), level=0) +- except ImportError: +- # We can just silently allow import failures to pass here. If we +- # got to this point it means that ``import pip._vendor.whatever`` +- # failed and so did ``import whatever``. Since we're importing this +- # upfront in an attempt to alias imports, not erroring here will +- # just mean we get a regular import error whenever pip *actually* +- # tries to import one of these modules to use it, which actually +- # gives us a better error message than we would have otherwise +- # gotten. +- pass +- else: +- sys.modules[vendored_name] = sys.modules[modulename] +- base, head = vendored_name.rsplit(".", 1) +- setattr(sys.modules[base], head, sys.modules[modulename]) ++ # We can just silently allow import failures to pass here. If we ++ # got to this point it means that ``import pip._vendor.whatever`` ++ # failed and so did ``import whatever``. Since we're importing this ++ # upfront in an attempt to alias imports, not erroring here will ++ # just mean we get a regular import error whenever pip *actually* ++ # tries to import one of these modules to use it, which actually ++ # gives us a better error message than we would have otherwise ++ # gotten. ++ pass ++ else: ++ sys.modules[vendored_name] = sys.modules[modulename] ++ base, head = vendored_name.rsplit(".", 1) ++ setattr(sys.modules[base], head, sys.modules[modulename]) + + + # If we're operating in a debundled setup, then we want to go ahead and trigger