mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-07 14:37:55 +00:00
fix(security): confine workspace existence checks
This commit is contained in:
parent
ee48c9c51e
commit
c7961d178f
2 changed files with 81 additions and 6 deletions
|
|
@ -16711,16 +16711,15 @@ def _existing_workspace_files(paths: list[str], workspace: Optional[str]) -> lis
|
|||
"""
|
||||
if not workspace:
|
||||
return []
|
||||
root = Path(str(workspace)).expanduser()
|
||||
from src.tool_execution import _resolve_tool_path_in_workspace
|
||||
|
||||
existing: list[str] = []
|
||||
for path in paths:
|
||||
candidate = Path(path).expanduser()
|
||||
if not candidate.is_absolute():
|
||||
candidate = root / candidate
|
||||
try:
|
||||
if candidate.is_file():
|
||||
resolved = _resolve_tool_path_in_workspace(str(workspace), str(path))
|
||||
if os.path.isfile(resolved):
|
||||
existing.append(path)
|
||||
except OSError:
|
||||
except (OSError, ValueError):
|
||||
continue
|
||||
return existing
|
||||
|
||||
|
|
|
|||
76
tests/test_existing_workspace_files_confinement.py
Normal file
76
tests/test_existing_workspace_files_confinement.py
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
from src.agent_loop import _existing_workspace_files
|
||||
|
||||
|
||||
def test_existing_workspace_files_accepts_relative_file_inside_workspace(tmp_path):
|
||||
workspace = tmp_path / "workspace"
|
||||
workspace.mkdir()
|
||||
target = workspace / "inside.py"
|
||||
target.write_text("pass\n")
|
||||
|
||||
assert _existing_workspace_files(
|
||||
["inside.py"],
|
||||
str(workspace),
|
||||
) == ["inside.py"]
|
||||
|
||||
|
||||
def test_existing_workspace_files_accepts_absolute_file_inside_workspace(tmp_path):
|
||||
workspace = tmp_path / "workspace"
|
||||
workspace.mkdir()
|
||||
target = workspace / "inside.py"
|
||||
target.write_text("pass\n")
|
||||
|
||||
assert _existing_workspace_files(
|
||||
[str(target)],
|
||||
str(workspace),
|
||||
) == [str(target)]
|
||||
|
||||
|
||||
def test_existing_workspace_files_rejects_absolute_file_outside_workspace(tmp_path):
|
||||
workspace = tmp_path / "workspace"
|
||||
workspace.mkdir()
|
||||
outside = tmp_path / "outside.py"
|
||||
outside.write_text("pass\n")
|
||||
|
||||
assert _existing_workspace_files(
|
||||
[str(outside)],
|
||||
str(workspace),
|
||||
) == []
|
||||
|
||||
|
||||
def test_existing_workspace_files_rejects_parent_traversal(tmp_path):
|
||||
workspace = tmp_path / "workspace"
|
||||
workspace.mkdir()
|
||||
outside = tmp_path / "outside.py"
|
||||
outside.write_text("pass\n")
|
||||
|
||||
assert _existing_workspace_files(
|
||||
["../outside.py"],
|
||||
str(workspace),
|
||||
) == []
|
||||
|
||||
|
||||
def test_existing_workspace_files_rejects_symlink_escape(tmp_path):
|
||||
workspace = tmp_path / "workspace"
|
||||
workspace.mkdir()
|
||||
outside = tmp_path / "outside.py"
|
||||
outside.write_text("pass\n")
|
||||
|
||||
escape = workspace / "escape.py"
|
||||
escape.symlink_to(outside)
|
||||
|
||||
assert _existing_workspace_files(
|
||||
["escape.py"],
|
||||
str(workspace),
|
||||
) == []
|
||||
|
||||
|
||||
def test_existing_workspace_files_supports_workspace_alias(tmp_path):
|
||||
workspace = tmp_path / "workspace"
|
||||
workspace.mkdir()
|
||||
target = workspace / "inside.py"
|
||||
target.write_text("pass\n")
|
||||
|
||||
assert _existing_workspace_files(
|
||||
["/workspace/inside.py"],
|
||||
str(workspace),
|
||||
) == ["/workspace/inside.py"]
|
||||
Loading…
Add table
Reference in a new issue