@@ -58,6 +58,25 @@ def usable(path: Path) -> bool:
5858 }
5959
6060
61+ def require_safe_fixture_ancestry (
62+ path : Path ,
63+ label : str ,
64+ * ,
65+ system_only : bool = False ,
66+ ) -> None :
67+ if not system_only :
68+ builder ._ORIGINAL_REQUIRE_SAFE_ANCESTRY (path , label )
69+ return
70+ current = path
71+ while True :
72+ info = os .lstat (current )
73+ if not stat .S_ISDIR (info .st_mode ) or stat .S_IMODE (info .st_mode ) & 0o022 :
74+ raise builder .BuildError (f"{ label } has unsafe system ancestry: { current } " )
75+ if current == current .parent :
76+ return
77+ current = current .parent
78+
79+
6180class ManifestFixture :
6281 def __init__ (self , temporary : Path ) -> None :
6382 self .root = temporary
@@ -180,6 +199,14 @@ class SealedRuntimeBuilderTests(unittest.TestCase):
180199 def setUp (self ) -> None :
181200 self .temporary = tempfile .TemporaryDirectory (prefix = "sealed-builder-test-" )
182201 self .root = Path (os .path .realpath (self .temporary .name ))
202+ if not hasattr (builder , "_ORIGINAL_REQUIRE_SAFE_ANCESTRY" ):
203+ builder ._ORIGINAL_REQUIRE_SAFE_ANCESTRY = builder ._require_safe_ancestry
204+ self .system_ancestry_patch = mock .patch .object (
205+ builder ,
206+ "_require_safe_ancestry" ,
207+ side_effect = require_safe_fixture_ancestry ,
208+ )
209+ self .system_ancestry_patch .start ()
183210 self .system_tools_patch = mock .patch .object (
184211 builder , "SYSTEM_TOOL_PATHS" , host_system_tool_paths ()
185212 )
@@ -189,6 +216,7 @@ def setUp(self) -> None:
189216 def tearDown (self ) -> None :
190217 builder ._unseal (self .root )
191218 self .system_tools_patch .stop ()
219+ self .system_ancestry_patch .stop ()
192220 self .temporary .cleanup ()
193221
194222 def test_manifest_accepts_exact_four_role_schema (self ) -> None :
0 commit comments