@@ -76,6 +76,39 @@ async def test_write_creates_parent_dirs(self, env: LocalEnvironment):
7676 data = await env .read_file ("sub/dir/file.txt" )
7777 assert data == b"nested"
7878
79+ @pytest .mark .asyncio
80+ async def test_absolute_path_inside_working_dir (self , env : LocalEnvironment ):
81+ """Absolute paths are accepted when they stay inside the workspace."""
82+ path = env .working_dir / "absolute.txt"
83+ await env .write_file (path , "absolute" )
84+ data = await env .read_file (path )
85+ assert data == b"absolute"
86+
87+ @pytest .mark .asyncio
88+ async def test_rejects_relative_path_escape (self , env : LocalEnvironment ):
89+ """Parent traversal cannot escape the workspace."""
90+ outside = env .working_dir .parent / "outside.txt"
91+ outside .write_text ("secret" , encoding = "utf-8" )
92+
93+ with pytest .raises (ValueError , match = "escapes working directory" ):
94+ await env .read_file (Path (".." ) / outside .name )
95+
96+ with pytest .raises (ValueError , match = "escapes working directory" ):
97+ await env .write_file (Path (".." ) / "write-outside.txt" , "nope" )
98+
99+ assert not (env .working_dir .parent / "write-outside.txt" ).exists ()
100+
101+ @pytest .mark .asyncio
102+ async def test_rejects_absolute_path_outside_working_dir (
103+ self , env : LocalEnvironment
104+ ):
105+ """Absolute paths outside the workspace are rejected."""
106+ outside = env .working_dir .parent / "outside-absolute.txt"
107+ outside .write_text ("secret" , encoding = "utf-8" )
108+
109+ with pytest .raises (ValueError , match = "escapes working directory" ):
110+ await env .read_file (outside )
111+
79112 @pytest .mark .asyncio
80113 async def test_read_nonexistent_raises (self , env : LocalEnvironment ):
81114 """Reading a missing file raises FileNotFoundError."""
0 commit comments