@@ -4311,6 +4311,30 @@ def test_sneaky_hardlink_fallback(self):
43114311 self .expect_file ("boom" , symlink_to = '../../link_here' )
43124312 self .expect_file ("c" , symlink_to = 'b' )
43134313
4314+ @symlink_test
4315+ def test_sneaky_hardlink_fallback_deep (self ):
4316+ # (CVE-2026-11940)
4317+ with ArchiveMaker () as arc :
4318+ arc .add ("a/b/s" , symlink_to = os .path .join (".." , "escape" ))
4319+ arc .add ("s" , hardlink_to = os .path .join ("a" , "b" , "s" ))
4320+
4321+ with self .check_context (arc .open (), 'data' ):
4322+ e = self .expect_exception (
4323+ tarfile .LinkFallbackError ,
4324+ "link 's' would be extracted as a copy of "
4325+ + "'a/b/s', which was rejected" )
4326+ self .assertIsInstance (e .__cause__ ,
4327+ tarfile .LinkOutsideDestinationError )
4328+
4329+ for filter in 'tar' , 'fully_trusted' :
4330+ with self .subTest (filter ), self .check_context (arc .open (), filter ):
4331+ if not os_helper .can_symlink ():
4332+ self .expect_file ("a/" )
4333+ self .expect_file ("a/b/" )
4334+ else :
4335+ self .expect_file ("a/b/s" , symlink_to = os .path .join ('..' , 'escape' ))
4336+ self .expect_file ("s" , symlink_to = os .path .join ('..' , 'escape' ))
4337+
43144338 @symlink_test
43154339 def test_exfiltration_via_symlink (self ):
43164340 # (CVE-2025-4138)
0 commit comments