Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b8f23e3

Browse files
[3.13] gh-157190: Fix tarfile data/tar filter bypass via hard link to a symlink (GH-157191) (GH-157192)
(cherry picked from commit 480ea4a) The backport to 3.13 and below includes a NEWS entry. Co-authored-by: Stan Ulbrych <[email protected]>
1 parent 9c193bd commit b8f23e3

3 files changed

Lines changed: 28 additions & 1 deletion

File tree

Lib/tarfile.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2738,7 +2738,11 @@ def makelink_with_filter(self, tarinfo, targetpath,
27382738
if os.path.lexists(targetpath):
27392739
# Avoid FileExistsError on following os.link.
27402740
os.unlink(targetpath)
2741-
os.link(tarinfo._link_target, targetpath)
2741+
# Resolve the target so the hard link points to the file
2742+
# itself. Otherwise os.link() may duplicate a symlink to a
2743+
# shallower location, where it's relative target escapes the
2744+
# destination directory. (CVE-2026-82049)
2745+
os.link(os.path.realpath(tarinfo._link_target), targetpath)
27422746
return
27432747
except symlink_exception:
27442748
keyerror_to_extracterror = True

Lib/test/test_tarfile.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4452,6 +4452,24 @@ def test_sneaky_hardlink_fallback_deep(self):
44524452
self.expect_file("a/b/s", symlink_to=os.path.join('..', 'escape'))
44534453
self.expect_file("s", symlink_to=os.path.join('..', 'escape'))
44544454

4455+
@symlink_test
4456+
@os_helper.skip_unless_hardlink
4457+
def test_sneaky_hardlink_relocation(self):
4458+
with ArchiveMaker() as arc:
4459+
arc.add("a/escape", content="decoy")
4460+
arc.add("a/b/s", symlink_to=os.path.join("..", "escape"))
4461+
arc.add("s", hardlink_to=os.path.join("a", "b", "s"))
4462+
4463+
for filter in 'data', 'tar':
4464+
with self.subTest(filter), self.check_context(arc.open(), filter):
4465+
self.expect_file("a/escape", content="decoy")
4466+
if os_helper.can_symlink():
4467+
self.expect_file("a/b/s", symlink_to=os.path.join('..', 'escape'))
4468+
else:
4469+
self.expect_file("a/b/s", content="decoy")
4470+
self.expect_file("s", content="decoy")
4471+
self.assertFalse((self.destdir / "s").is_symlink())
4472+
44554473
@symlink_test
44564474
def test_exfiltration_via_symlink(self):
44574475
# (CVE-2025-4138)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fixed a vulnerability in the :mod:`tarfile` ``data`` and ``tar`` extraction
2+
filters where a crafted archive using a hard link to a symbolic link could
3+
change the permissions and modification time of a file outside the
4+
destination directory, and expose its contents inside the extracted tree.
5+
This addresses :cve:`2026-82049`.

0 commit comments

Comments
 (0)