diff --git a/SOURCES/CVE-2019-20916.patch b/SOURCES/CVE-2019-20916.patch new file mode 100644 index 0000000..2afc4ed --- /dev/null +++ b/SOURCES/CVE-2019-20916.patch @@ -0,0 +1,68 @@ +From 843735d9dc129eb34f16c4c08576ac5f742971f6 Mon Sep 17 00:00:00 2001 +From: Lumir Balhar +Date: Tue, 17 May 2022 12:44:01 +0200 +Subject: [PATCH] CVE-2019-20916 + +--- + download.py | 31 +++++++++++++++++++++++++----- + 1 file changed, 26 insertions(+), 5 deletions(-) + +diff --git a/download.py b/download.py +index 54d3131..e49130b 100644 +--- a/download.py ++++ b/download.py +@@ -54,7 +54,8 @@ __all__ = ['get_file_content', + 'is_url', 'url_to_path', 'path_to_url', + 'is_archive_file', 'unpack_vcs_link', + 'unpack_file_url', 'is_vcs_url', 'is_file_url', +- 'unpack_http_url', 'unpack_url'] ++ 'unpack_http_url', 'unpack_url', ++ 'parse_content_disposition', 'sanitize_content_filename'] + + + logger = logging.getLogger(__name__) +@@ -824,6 +825,29 @@ def unpack_url(link, location, download_dir=None, + 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 +888,7 @@ def _download_http_url(link, session, temp_dir, hashes): + # 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) +-- +2.35.3 + diff --git a/SPECS/python-virtualenv.spec b/SPECS/python-virtualenv.spec index 669be2f..deec25f 100644 --- a/SPECS/python-virtualenv.spec +++ b/SPECS/python-virtualenv.spec @@ -1,6 +1,6 @@ Name: python-virtualenv Version: 15.1.0 -Release: 6%{?dist} +Release: 7%{?dist} Summary: Tool to create isolated Python environments Group: Development/Languages @@ -41,6 +41,10 @@ Patch4: dummy-certifi.patch # https://github.com/pypa/virtualenv/pull/1252 Patch5: dont-fail-on-missing-requests-cert.patch +# Fix CVE-2019-20916: directory traversal in _download_http_url() function within the bundled pip wheel +# Backported from upstream: https://github.com/pypa/pip/pull/6418 +Patch6: CVE-2019-20916.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildArch: noarch @@ -81,6 +85,9 @@ pushd pip/_vendor/requests/ %patch3 -p1 %patch4 -p1 popd # out of wheel +pushd pip +%patch6 -p1 +popd sed -i '/\.pem/d' pip-9.0.1.dist-info/RECORD # Replace the pip folder in the zip archive (.whl) zip -r pip-9.0.1-py2.py3-none-any.whl pip pip-9.0.1.dist-info @@ -128,6 +135,10 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Tue May 17 2022 Lumír Balhar - 15.1.0-7 +- Security fix for CVE-2019-20916 for the bundled pip wheel +Resolves: rhbz#1868135 + * Wed Feb 23 2022 Charalampos Stratakis - 15.1.0-6 - Require again python-setuptools instead of python2-setuptools Resolves: rhbz#2054827