@@ -4182,6 +4182,30 @@ def test_sneaky_hardlink_fallback(self):
41824182 self .expect_file ("boom" , symlink_to = '../../link_here' )
41834183 self .expect_file ("c" , symlink_to = 'b' )
41844184
4185+ @symlink_test
4186+ def test_sneaky_hardlink_fallback_deep (self ):
4187+ # (CVE-2026-11940)
4188+ with ArchiveMaker () as arc :
4189+ arc .add ("a/b/s" , symlink_to = os .path .join (".." , "escape" ))
4190+ arc .add ("s" , hardlink_to = os .path .join ("a" , "b" , "s" ))
4191+
4192+ with self .check_context (arc .open (), 'data' ):
4193+ e = self .expect_exception (
4194+ tarfile .LinkFallbackError ,
4195+ "link 's' would be extracted as a copy of "
4196+ + "'a/b/s', which was rejected" )
4197+ self .assertIsInstance (e .__cause__ ,
4198+ tarfile .LinkOutsideDestinationError )
4199+
4200+ for filter in 'tar' , 'fully_trusted' :
4201+ with self .subTest (filter ), self .check_context (arc .open (), filter ):
4202+ if not os_helper .can_symlink ():
4203+ self .expect_file ("a/" )
4204+ self .expect_file ("a/b/" )
4205+ else :
4206+ self .expect_file ("a/b/s" , symlink_to = os .path .join ('..' , 'escape' ))
4207+ self .expect_file ("s" , symlink_to = os .path .join ('..' , 'escape' ))
4208+
41854209 @symlink_test
41864210 def test_exfiltration_via_symlink (self ):
41874211 # (CVE-2025-4138)
0 commit comments