From 7f0891d88a65378ede3c36f554dd7d2f58e866a6 Mon Sep 17 00:00:00 2001 From: Charalampos Stratakis Date: Wed, 24 Apr 2024 03:26:11 +0200 Subject: [PATCH] Use tarfile.data_filter for extracting (CVE-2007-4559, PEP-721, PEP-706) - Require Python with tarfile filters - Resolves: RHEL-25820 --- cve-2007-4559-tarfile.patch | 85 +++++++++++++++++++++++++++++++++++++ python-pip.spec | 8 ++++ 2 files changed, 93 insertions(+) create mode 100644 cve-2007-4559-tarfile.patch diff --git a/cve-2007-4559-tarfile.patch b/cve-2007-4559-tarfile.patch new file mode 100644 index 0000000..4b15642 --- /dev/null +++ b/cve-2007-4559-tarfile.patch @@ -0,0 +1,85 @@ +From 1819805f2019c731bcaefd6b12fd814790f88fcd Mon Sep 17 00:00:00 2001 +From: Lumir Balhar +Date: Tue, 19 Mar 2024 12:43:07 +0100 +Subject: [PATCH] cve-2007-4559-tarfile + +Minimal patch for pip +--- + src/pip/_internal/utils/unpacking.py | 7 +++++++ + src/pip/_vendor/distlib/util.py | 13 +++++++++++++ + tests/unit/test_utils_unpacking.py | 17 +++++++++++++++++ + 3 files changed, 37 insertions(+) + +diff --git a/src/pip/_internal/utils/unpacking.py b/src/pip/_internal/utils/unpacking.py +index 5f63f97..c31542f 100644 +--- a/src/pip/_internal/utils/unpacking.py ++++ b/src/pip/_internal/utils/unpacking.py +@@ -184,6 +184,13 @@ def untar_file(filename: str, location: str) -> None: + "outside target directory ({})" + ) + raise InstallationError(message.format(filename, path, location)) ++ ++ # Call the `data` filter for its side effect (raising exception) ++ try: ++ tarfile.data_filter(member.replace(name=fn), location) ++ except tarfile.LinkOutsideDestinationError: ++ pass ++ + if member.isdir(): + ensure_dir(path) + elif member.issym(): +diff --git a/src/pip/_vendor/distlib/util.py b/src/pip/_vendor/distlib/util.py +index 80bfc86..7e0941a 100644 +--- a/src/pip/_vendor/distlib/util.py ++++ b/src/pip/_vendor/distlib/util.py +@@ -1249,6 +1249,19 @@ def unarchive(archive_filename, dest_dir, format=None, check=True): + for tarinfo in archive.getmembers(): + if not isinstance(tarinfo.name, text_type): + tarinfo.name = tarinfo.name.decode('utf-8') ++ ++ # Limit extraction of dangerous items, if this Python ++ # allows it easily. If not, just trust the input. ++ # See: https://docs.python.org/3/library/tarfile.html#extraction-filters ++ def extraction_filter(member, path): ++ """Run tarfile.tar_fillter, but raise the expected ValueError""" ++ # This is only called if the current Python has tarfile filters ++ try: ++ return tarfile.tar_filter(member, path) ++ except tarfile.FilterError as exc: ++ raise ValueError(str(exc)) ++ archive.extraction_filter = extraction_filter ++ + archive.extractall(dest_dir) + + finally: +diff --git a/tests/unit/test_utils_unpacking.py b/tests/unit/test_utils_unpacking.py +index ccb7a30..05324ad 100644 +--- a/tests/unit/test_utils_unpacking.py ++++ b/tests/unit/test_utils_unpacking.py +@@ -171,6 +171,23 @@ class TestUnpackArchives: + test_tar = self.make_tar_file("test_tar.tar", files) + untar_file(test_tar, self.tempdir) + ++ def test_unpack_tar_filter(self) -> None: ++ """ ++ Test that the tarfile.data_filter is used to disallow dangerous ++ behaviour (PEP-721) ++ """ ++ test_tar = os.path.join(self.tempdir, "test_tar_filter.tar") ++ with tarfile.open(test_tar, "w") as mytar: ++ file_tarinfo = tarfile.TarInfo("bad-link") ++ file_tarinfo.type = tarfile.SYMTYPE ++ file_tarinfo.linkname = "../../../../pwn" ++ mytar.addfile(file_tarinfo, io.BytesIO(b"")) ++ with pytest.raises(InstallationError) as e: ++ untar_file(test_tar, self.tempdir) ++ ++ assert "is outside the destination" in str(e.value) ++ ++ + + def test_unpack_tar_unicode(tmpdir: Path) -> None: + test_tar = tmpdir / "test.tar" +-- +2.44.0 + diff --git a/python-pip.spec b/python-pip.spec index 452ec3d..b65fd56 100644 --- a/python-pip.spec +++ b/python-pip.spec @@ -82,6 +82,14 @@ Patch: nowarn-pip._internal.main.patch # Upstream issue: https://github.com/pypa/packaging/issues/368 Patch: no-version-warning.patch +# CVE-2007-4559, PEP-721, PEP-706: Use tarfile.data_filter for extracting +# - Minimal downstream-only patch, to be replaced by upstream solution +# proposed in https://github.com/pypa/pip/pull/12214 +# - Test patch submitted upstream in the above pull request +# - Patch for vendored distlib, accepted upstream: +# https://github.com/pypa/distlib/pull/201 +Patch: cve-2007-4559-tarfile.patch + %description pip is a package management system used to install and manage software packages written in Python. Many packages can be found in the Python Package Index