diff --git a/package/python3/0017-Fix-symlink-escape-via-tarfile-hardlink-extraction-fallback.patch b/package/python3/0017-Fix-symlink-escape-via-tarfile-hardlink-extraction-fallback.patch new file mode 100644 index 0000000000..d5ec1626bf --- /dev/null +++ b/package/python3/0017-Fix-symlink-escape-via-tarfile-hardlink-extraction-fallback.patch @@ -0,0 +1,77 @@ +From d0ba16dce6df2f68e8968699d5c247eddeef9960 Mon Sep 17 00:00:00 2001 +From: Stan Ulbrych +Date: Tue, 23 Jun 2026 14:31:38 +0100 +Subject: [PATCH] gh-151558: Fix symlink escape via `tarfile` + hardlink-extraction fallback (GH-151559) (cherry picked from commit + 27dd970bf6b17ebca7c8ed486a40ab043ed7af8f) + +Co-authored-by: Stan Ulbrych + +Upstream: https://github.com/python/cpython/pull/152000 +CVE: CVE-2026-11940 +Signed-off-by: Titouan Christophe +--- + Lib/tarfile.py | 3 +++ + Lib/test/test_tarfile.py | 24 +++++++++++++++++++ + ...-06-10-13-08-19.gh-issue-151558.mL74i2.rst | 3 +++ + 3 files changed, 30 insertions(+) + create mode 100644 Misc/NEWS.d/next/Security/2026-06-10-13-08-19.gh-issue-151558.mL74i2.rst + +diff --git a/Lib/tarfile.py b/Lib/tarfile.py +index 461ec16dcd8592..73e9ece4153170 100755 +--- a/Lib/tarfile.py ++++ b/Lib/tarfile.py +@@ -2677,6 +2677,9 @@ def makelink_with_filter(self, tarinfo, targetpath, + "makelink_with_filter: if filter_function is not None, " + + "extraction_root must also not be None") + try: ++ filter_function( ++ unfiltered.replace(name=tarinfo.name, deep=False), ++ extraction_root) + filtered = filter_function(unfiltered, extraction_root) + except _FILTER_ERRORS as cause: + raise LinkFallbackError(tarinfo, unfiltered.name) from cause +diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py +index 9a4c5a301b30d0..902538d2262ceb 100644 +--- a/Lib/test/test_tarfile.py ++++ b/Lib/test/test_tarfile.py +@@ -4182,6 +4182,30 @@ def test_sneaky_hardlink_fallback(self): + self.expect_file("boom", symlink_to='../../link_here') + self.expect_file("c", symlink_to='b') + ++ @symlink_test ++ def test_sneaky_hardlink_fallback_deep(self): ++ # (CVE-2026-11940) ++ with ArchiveMaker() as arc: ++ arc.add("a/b/s", symlink_to=os.path.join("..", "escape")) ++ arc.add("s", hardlink_to=os.path.join("a", "b", "s")) ++ ++ with self.check_context(arc.open(), 'data'): ++ e = self.expect_exception( ++ tarfile.LinkFallbackError, ++ "link 's' would be extracted as a copy of " ++ + "'a/b/s', which was rejected") ++ self.assertIsInstance(e.__cause__, ++ tarfile.LinkOutsideDestinationError) ++ ++ for filter in 'tar', 'fully_trusted': ++ with self.subTest(filter), self.check_context(arc.open(), filter): ++ if not os_helper.can_symlink(): ++ self.expect_file("a/") ++ self.expect_file("a/b/") ++ else: ++ self.expect_file("a/b/s", symlink_to=os.path.join('..', 'escape')) ++ self.expect_file("s", symlink_to=os.path.join('..', 'escape')) ++ + @symlink_test + def test_exfiltration_via_symlink(self): + # (CVE-2025-4138) +diff --git a/Misc/NEWS.d/next/Security/2026-06-10-13-08-19.gh-issue-151558.mL74i2.rst b/Misc/NEWS.d/next/Security/2026-06-10-13-08-19.gh-issue-151558.mL74i2.rst +new file mode 100644 +index 00000000000000..74459d5680e21a +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2026-06-10-13-08-19.gh-issue-151558.mL74i2.rst +@@ -0,0 +1,3 @@ ++Fixed an vulnerability in the :mod:`tarfile` ``data`` and ``tar`` extraction ++filters where crafted archives could create a symlink pointing outside the ++destination directory. This was a bypass of :cve:`2025-4330`. diff --git a/package/python3/python3.mk b/package/python3/python3.mk index 1c181f0d33..4fd16b4204 100644 --- a/package/python3/python3.mk +++ b/package/python3/python3.mk @@ -21,6 +21,8 @@ PYTHON3_IGNORE_CVES += CVE-2026-7774 PYTHON3_IGNORE_CVES += CVE-2026-8328 # 0016-prevent-bz2-decompressor-reuse-after-errors.patch PYTHON3_IGNORE_CVES += CVE-2026-9669 +# 0017-Fix-symlink-escape-via-tarfile-hardlink-extraction-fallback.patch +PYTHON3_IGNORE_CVES += CVE-2026-11940 # This host Python is installed in $(HOST_DIR), as it is needed when # cross-compiling third-party Python modules.