Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Fix bypass
  • Loading branch information
StanFromIreland committed Jun 10, 2026
commit 9f81791353d8f1a321b22546fc5e9ef58fb0fc21
4 changes: 3 additions & 1 deletion Lib/tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -2784,7 +2784,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:
filtered = filter_function(unfiltered, extraction_root)
filtered = filter_function(
unfiltered.replace(name=tarinfo.name, deep=False),
extraction_root)
except _FILTER_ERRORS as cause:
raise LinkFallbackError(tarinfo, unfiltered.name) from cause
if filtered is not None:
Expand Down
27 changes: 27 additions & 0 deletions Lib/test/test_tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -4413,6 +4413,33 @@ 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):
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'):
if not os_helper.can_symlink() or sys.platform == "win32":
# See notes in test_sneaky_hardlink_fallback.
self.expect_exception(tarfile.LinkOutsideDestinationError)
else:
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/b/s")
self.expect_file("s")
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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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`.