Fix CVE-2026-11940: symlink escape via tarfile hardlink fallback
Security fix for CVE-2026-11940: a symlink escape vulnerability
via tarfile hardlink-extraction fallback. The new backport patch
(00491-cve-2026-11940.patch) adds a filter check on the
hardlink's target name before performing the fallback copy,
preventing extraction of symlinks that point outside the
destination directory.
CVE: CVE-2026-11940
Upstream patches:
- 27dd970bf6.patch
Resolves: RHEL-227194
This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent.
Assisted-by: Ymir
This commit is contained in:
parent
7c4eff367d
commit
294a585edf
59
00492-cve-2026-11940.patch
Normal file
59
00492-cve-2026-11940.patch
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
From a235238fe0884e85cdacbc986a4749c5c4717212 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Stan Ulbrych <stan@python.org>
|
||||||
|
Date: Tue, 23 Jun 2026 14:31:38 +0100
|
||||||
|
Subject: [PATCH] gh-151558: Fix symlink escape via `tarfile`
|
||||||
|
hardlink-extraction fallback (GH-151559)
|
||||||
|
|
||||||
|
---
|
||||||
|
Lib/tarfile.py | 3 +++
|
||||||
|
Lib/test/test_tarfile.py | 23 +++++++++++++++++++++++
|
||||||
|
2 files changed, 26 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
|
||||||
|
index 3e03ebf..61d7e46 100755
|
||||||
|
--- a/Lib/tarfile.py
|
||||||
|
+++ b/Lib/tarfile.py
|
||||||
|
@@ -2642,6 +2642,9 @@ class TarFile(object):
|
||||||
|
"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 0a7586a..d43559a 100644
|
||||||
|
--- a/Lib/test/test_tarfile.py
|
||||||
|
+++ b/Lib/test/test_tarfile.py
|
||||||
|
@@ -3543,6 +3543,29 @@ class TestExtractionFilters(unittest.TestCase):
|
||||||
|
self.expect_file("boom", symlink_to='../../link_here')
|
||||||
|
self.expect_file("c", symlink_to='b')
|
||||||
|
|
||||||
|
+ 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 support.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'))
|
||||||
|
+
|
||||||
|
def test_exfiltration_via_symlink(self):
|
||||||
|
# (CVE-2025-4138)
|
||||||
|
# Test changing symlinks that result in a symlink pointing outside
|
||||||
13
python3.spec
13
python3.spec
@ -14,7 +14,7 @@ URL: https://www.python.org/
|
|||||||
# WARNING When rebasing to a new Python version,
|
# WARNING When rebasing to a new Python version,
|
||||||
# remember to update the python3-docs package as well
|
# remember to update the python3-docs package as well
|
||||||
Version: %{pybasever}.8
|
Version: %{pybasever}.8
|
||||||
Release: 77%{?dist}
|
Release: 78%{?dist}
|
||||||
License: Python
|
License: Python
|
||||||
|
|
||||||
|
|
||||||
@ -1028,6 +1028,12 @@ Patch482: 00482-cve-2026-6100.patch
|
|||||||
# only joined and parsed once enough has piled up.
|
# only joined and parsed once enough has piled up.
|
||||||
Patch490: 00490-cve-2026-15308.patch
|
Patch490: 00490-cve-2026-15308.patch
|
||||||
|
|
||||||
|
# 00492 #
|
||||||
|
# CVE-2026-11940
|
||||||
|
#
|
||||||
|
# gh-151558: Fix symlink escape via tarfile hardlink-extraction fallback (GH-151559)
|
||||||
|
Patch492: 00492-cve-2026-11940.patch
|
||||||
|
|
||||||
# (New patches go here ^^^)
|
# (New patches go here ^^^)
|
||||||
#
|
#
|
||||||
# When adding new patches to "python" and "python3" in Fedora, EL, etc.,
|
# When adding new patches to "python" and "python3" in Fedora, EL, etc.,
|
||||||
@ -1409,6 +1415,7 @@ GIT_DIR=$PWD git apply %{PATCH351}
|
|||||||
%patch480 -p1
|
%patch480 -p1
|
||||||
%patch482 -p1
|
%patch482 -p1
|
||||||
%patch490 -p1
|
%patch490 -p1
|
||||||
|
%patch492 -p1
|
||||||
|
|
||||||
# Remove files that should be generated by the build
|
# Remove files that should be generated by the build
|
||||||
# (This is after patching, so that we can use patches directly from upstream)
|
# (This is after patching, so that we can use patches directly from upstream)
|
||||||
@ -2340,6 +2347,10 @@ fi
|
|||||||
# ======================================================
|
# ======================================================
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Aug 06 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 3.6.8-78
|
||||||
|
- Security fix for CVE-2026-11940
|
||||||
|
Resolves: RHEL-227194
|
||||||
|
|
||||||
* Fri Jul 10 2026 Lumír Balhar <lbalhar@redhat.com> - 3.6.8-77
|
* Fri Jul 10 2026 Lumír Balhar <lbalhar@redhat.com> - 3.6.8-77
|
||||||
- Security fix for CVE-2026-15308
|
- Security fix for CVE-2026-15308
|
||||||
Resolves: RHEL-193772
|
Resolves: RHEL-193772
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user