Use tarfile.data_filter for extracting (CVE-2007-4559, PEP-721, PEP-706)

- Require Python with tarfile filters
- Resolves: RHEL-25820
This commit is contained in:
Charalampos Stratakis 2024-04-24 03:26:11 +02:00
parent 3c290026a9
commit 7f0891d88a
2 changed files with 93 additions and 0 deletions

View File

@ -0,0 +1,85 @@
From 1819805f2019c731bcaefd6b12fd814790f88fcd Mon Sep 17 00:00:00 2001
From: Lumir Balhar <lbalhar@redhat.com>
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

View File

@ -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