@@ -168,6 +168,25 @@ async def test_local_file_rejects_symlinked_source_leaf(tmp_path: Path) -> None:
168168 assert session .writes == {}
169169
170170
171+ @pytest .mark .asyncio
172+ async def test_local_file_rejects_symlinked_source_before_checksum (tmp_path : Path ) -> None :
173+ target_dir = tmp_path / "secret-dir"
174+ target_dir .mkdir ()
175+ _symlink_or_skip (tmp_path / "link.txt" , target_dir , target_is_directory = True )
176+ session = _RecordingSession ()
177+
178+ with pytest .raises (LocalFileReadError ) as excinfo :
179+ await LocalFile (src = Path ("link.txt" )).apply (
180+ session ,
181+ Path ("/workspace/copied.txt" ),
182+ tmp_path ,
183+ )
184+
185+ assert excinfo .value .context ["reason" ] == "symlink_not_supported"
186+ assert excinfo .value .context ["child" ] == "link.txt"
187+ assert session .writes == {}
188+
189+
171190@pytest .mark .asyncio
172191async def test_local_dir_copy_falls_back_when_safe_dir_fd_open_unavailable (
173192 monkeypatch : pytest .MonkeyPatch ,
@@ -200,6 +219,9 @@ async def test_local_dir_copy_revalidates_swapped_paths_during_open(
200219 monkeypatch : pytest .MonkeyPatch ,
201220 tmp_path : Path ,
202221) -> None :
222+ if not artifacts_module ._OPEN_SUPPORTS_DIR_FD or not artifacts_module ._HAS_O_DIRECTORY :
223+ pytest .skip ("safe dir_fd open pinning is unavailable on this platform" )
224+
203225 src_root = tmp_path / "src"
204226 src_root .mkdir ()
205227 src_file = src_root / "safe.txt"
@@ -221,7 +243,7 @@ def swap_then_open(
221243 nonlocal swapped
222244 if path == "safe.txt" and not swapped :
223245 src_file .unlink ()
224- src_file . symlink_to ( secret )
246+ _symlink_or_skip ( src_file , secret )
225247 swapped = True
226248 if dir_fd is None :
227249 return original_open (path , flags , mode )
@@ -251,6 +273,9 @@ async def test_local_dir_copy_pins_parent_directories_during_open(
251273 monkeypatch : pytest .MonkeyPatch ,
252274 tmp_path : Path ,
253275) -> None :
276+ if not artifacts_module ._OPEN_SUPPORTS_DIR_FD or not artifacts_module ._HAS_O_DIRECTORY :
277+ pytest .skip ("safe dir_fd open pinning is unavailable on this platform" )
278+
254279 src_root = tmp_path / "src"
255280 src_root .mkdir ()
256281 nested_dir = src_root / "nested"
@@ -275,7 +300,7 @@ def swap_parent_then_open(
275300 nonlocal swapped
276301 if path == "safe.txt" and not swapped :
277302 (src_root / "nested" ).rename (src_root / "nested-original" )
278- (src_root / "nested" ). symlink_to ( secret_dir , target_is_directory = True )
303+ _symlink_or_skip (src_root / "nested" , secret_dir , target_is_directory = True )
279304 swapped = True
280305 if dir_fd is None :
281306 return original_open (path , flags , mode )
@@ -300,6 +325,9 @@ async def test_local_dir_apply_rejects_source_root_swapped_to_symlink_after_vali
300325 monkeypatch : pytest .MonkeyPatch ,
301326 tmp_path : Path ,
302327) -> None :
328+ if not artifacts_module ._OPEN_SUPPORTS_DIR_FD or not artifacts_module ._HAS_O_DIRECTORY :
329+ pytest .skip ("safe dir_fd open pinning is unavailable on this platform" )
330+
303331 src_root = tmp_path / "src"
304332 src_root .mkdir ()
305333 (src_root / "safe.txt" ).write_text ("safe" , encoding = "utf-8" )
@@ -321,7 +349,7 @@ def swap_root_then_open(
321349 nonlocal swapped
322350 if path == "src" and dir_fd is not None and not swapped :
323351 src_root .rename (tmp_path / "src-original" )
324- (tmp_path / "src" ). symlink_to ( secret_dir , target_is_directory = True )
352+ _symlink_or_skip (tmp_path / "src" , secret_dir , target_is_directory = True )
325353 swapped = True
326354 if dir_fd is None :
327355 return original_open (path , flags , mode )
@@ -393,7 +421,7 @@ async def test_local_dir_rejects_symlinked_source_ancestors(tmp_path: Path) -> N
393421 nested_dir = target_dir / "sub"
394422 nested_dir .mkdir ()
395423 (nested_dir / "secret.txt" ).write_text ("secret" , encoding = "utf-8" )
396- (tmp_path / "link" ). symlink_to ( target_dir , target_is_directory = True )
424+ _symlink_or_skip (tmp_path / "link" , target_dir , target_is_directory = True )
397425 session = _RecordingSession ()
398426
399427 with pytest .raises (LocalDirReadError ) as excinfo :
@@ -409,7 +437,7 @@ async def test_local_dir_rejects_symlinked_source_root(tmp_path: Path) -> None:
409437 target_dir = tmp_path / "secret-dir"
410438 target_dir .mkdir ()
411439 (target_dir / "secret.txt" ).write_text ("secret" , encoding = "utf-8" )
412- (tmp_path / "src" ). symlink_to ( target_dir , target_is_directory = True )
440+ _symlink_or_skip (tmp_path / "src" , target_dir , target_is_directory = True )
413441 session = _RecordingSession ()
414442
415443 with pytest .raises (LocalDirReadError ) as excinfo :
@@ -427,7 +455,7 @@ async def test_local_dir_rejects_symlinked_files(tmp_path: Path) -> None:
427455 (src_root / "safe.txt" ).write_text ("safe" , encoding = "utf-8" )
428456 secret = tmp_path / "secret.txt"
429457 secret .write_text ("secret" , encoding = "utf-8" )
430- (src_root / "link.txt" ). symlink_to ( secret )
458+ _symlink_or_skip (src_root / "link.txt" , secret )
431459 session = _RecordingSession ()
432460
433461 with pytest .raises (LocalDirReadError ) as excinfo :
@@ -446,7 +474,7 @@ async def test_local_dir_rejects_symlinked_directories(tmp_path: Path) -> None:
446474 target_dir = tmp_path / "secret-dir"
447475 target_dir .mkdir ()
448476 (target_dir / "secret.txt" ).write_text ("secret" , encoding = "utf-8" )
449- (src_root / "linked-dir" ). symlink_to ( target_dir , target_is_directory = True )
477+ _symlink_or_skip (src_root / "linked-dir" , target_dir , target_is_directory = True )
450478 session = _RecordingSession ()
451479
452480 with pytest .raises (LocalDirReadError ) as excinfo :
@@ -492,10 +520,11 @@ async def test_git_repo_uses_fetch_checkout_path_for_commit_refs() -> None:
492520@pytest .mark .asyncio
493521async def test_dir_metadata_strips_file_type_bits_before_chmod () -> None :
494522 session = _RecordingSession ()
523+ dest = Path ("/workspace/dir" )
495524
496- await Dir ()._apply_metadata (session , Path ( "/workspace/dir" ) )
525+ await Dir ()._apply_metadata (session , dest )
497526
498- assert ("chmod" , "0755" , "/workspace/dir" ) in session .exec_calls
527+ assert ("chmod" , "0755" , str ( dest ) ) in session .exec_calls
499528
500529
501530@pytest .mark .asyncio
@@ -526,5 +555,5 @@ async def test_apply_manifest_raises_on_chgrp_failure() -> None:
526555 with pytest .raises (ExecNonZeroError ):
527556 await session .apply_manifest ()
528557
529- assert ("chgrp" , "sandbox-user" , "/workspace/copied.txt" ) in session .exec_calls
558+ assert ("chgrp" , "sandbox-user" , str ( Path ( "/workspace/copied.txt" )) ) in session .exec_calls
530559 assert not any (call [0 ] == "chmod" for call in session .exec_calls )
0 commit comments