@@ -4384,6 +4384,30 @@ def test_sneaky_hardlink_fallback(self):
43844384 self .expect_file ("boom" , symlink_to = '../../link_here' )
43854385 self .expect_file ("c" , symlink_to = 'b' )
43864386
4387+ @symlink_test
4388+ def test_sneaky_hardlink_fallback_deep (self ):
4389+ # (CVE-2026-11940)
4390+ with ArchiveMaker () as arc :
4391+ arc .add ("a/b/s" , symlink_to = os .path .join (".." , "escape" ))
4392+ arc .add ("s" , hardlink_to = os .path .join ("a" , "b" , "s" ))
4393+
4394+ with self .check_context (arc .open (), 'data' ):
4395+ e = self .expect_exception (
4396+ tarfile .LinkFallbackError ,
4397+ "link 's' would be extracted as a copy of "
4398+ + "'a/b/s', which was rejected" )
4399+ self .assertIsInstance (e .__cause__ ,
4400+ tarfile .LinkOutsideDestinationError )
4401+
4402+ for filter in 'tar' , 'fully_trusted' :
4403+ with self .subTest (filter ), self .check_context (arc .open (), filter ):
4404+ if not os_helper .can_symlink ():
4405+ self .expect_file ("a/" )
4406+ self .expect_file ("a/b/" )
4407+ else :
4408+ self .expect_file ("a/b/s" , symlink_to = os .path .join ('..' , 'escape' ))
4409+ self .expect_file ("s" , symlink_to = os .path .join ('..' , 'escape' ))
4410+
43874411 @symlink_test
43884412 def test_exfiltration_via_symlink (self ):
43894413 # (CVE-2025-4138)
0 commit comments