Skip to content

Commit 9f81791

Browse files
Fix bypass
1 parent 9fdbade commit 9f81791

3 files changed

Lines changed: 33 additions & 1 deletion

File tree

Lib/tarfile.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2784,7 +2784,9 @@ def makelink_with_filter(self, tarinfo, targetpath,
27842784
"makelink_with_filter: if filter_function is not None, "
27852785
+ "extraction_root must also not be None")
27862786
try:
2787-
filtered = filter_function(unfiltered, extraction_root)
2787+
filtered = filter_function(
2788+
unfiltered.replace(name=tarinfo.name, deep=False),
2789+
extraction_root)
27882790
except _FILTER_ERRORS as cause:
27892791
raise LinkFallbackError(tarinfo, unfiltered.name) from cause
27902792
if filtered is not None:

Lib/test/test_tarfile.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4413,6 +4413,33 @@ def test_sneaky_hardlink_fallback(self):
44134413
self.expect_file("boom", symlink_to='../../link_here')
44144414
self.expect_file("c", symlink_to='b')
44154415

4416+
@symlink_test
4417+
def test_sneaky_hardlink_fallback_deep(self):
4418+
with ArchiveMaker() as arc:
4419+
arc.add("a/b/s", symlink_to=os.path.join("..", "escape"))
4420+
arc.add("s", hardlink_to=os.path.join("a", "b", "s"))
4421+
4422+
with self.check_context(arc.open(), 'data'):
4423+
if not os_helper.can_symlink() or sys.platform == "win32":
4424+
# See notes in test_sneaky_hardlink_fallback.
4425+
self.expect_exception(tarfile.LinkOutsideDestinationError)
4426+
else:
4427+
e = self.expect_exception(
4428+
tarfile.LinkFallbackError,
4429+
"link 's' would be extracted as a copy of "
4430+
+ "'a/b/s', which was rejected")
4431+
self.assertIsInstance(e.__cause__,
4432+
tarfile.LinkOutsideDestinationError)
4433+
4434+
for filter in 'tar', 'fully_trusted':
4435+
with self.subTest(filter), self.check_context(arc.open(), filter):
4436+
if not os_helper.can_symlink():
4437+
self.expect_file("a/b/s")
4438+
self.expect_file("s")
4439+
else:
4440+
self.expect_file("a/b/s", symlink_to=os.path.join('..', 'escape'))
4441+
self.expect_file("s", symlink_to=os.path.join('..', 'escape'))
4442+
44164443
@symlink_test
44174444
def test_exfiltration_via_symlink(self):
44184445
# (CVE-2025-4138)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fixed an vulnerability in the :mod:`tarfile` ``data`` and ``tar`` extraction
2+
filters where crafted archives could create a symlink pointing outside the
3+
destination directory. This was a bypass of :cve:`2025-4330`.

0 commit comments

Comments
 (0)