"""Tests for the agent's read-tool sandbox boundary (no model calls).""" from pathlib import Path from langchain_core.tools import BaseTool from skill_eval_runner.agent import make_tools from skill_eval_runner.config import ArtifactConfig def _read_file_tool(base: Path) -> BaseTool: """Build the tools and return the ``read_file`` tool.""" tools = make_tools(base, ArtifactConfig(mode="final_message"), {}) return next(t for t in tools if t.name == "read_file") def test_read_file_allows_paths_inside_sandbox(tmp_path: Path) -> None: """A path within the fixture root is read normally.""" base = tmp_path / "root" base.mkdir() (base / "a.txt").write_text("hello") assert _read_file_tool(base).invoke({"path": "a.txt"}) == "hello" def test_read_file_blocks_sibling_with_shared_prefix(tmp_path: Path) -> None: """A sibling dir whose name shares the root's prefix (root vs root2) is rejected.""" base = tmp_path / "root" base.mkdir() sibling = tmp_path / "root2" sibling.mkdir() (sibling / "secret.txt").write_text("nope") result = _read_file_tool(base).invoke({"path": "../root2/secret.txt"}) assert "outside the allowed directory" in result