111 lines
3.9 KiB
Python
111 lines
3.9 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import stat
|
|
import sys
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
|
|
from opensquilla.sandbox import sensitive_paths
|
|
from opensquilla.tools.builtin import code_exec
|
|
from opensquilla.tools.types import ToolContext, current_tool_context
|
|
|
|
|
|
def test_code_exec_prefers_current_interpreter_when_path_has_no_python(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
) -> None:
|
|
python_bin = tmp_path / ("python.exe" if os.name == "nt" else "python")
|
|
python_bin.write_text("", encoding="utf-8")
|
|
python_bin.chmod(python_bin.stat().st_mode | stat.S_IXUSR)
|
|
monkeypatch.setattr(sys, "executable", str(python_bin))
|
|
monkeypatch.setattr(code_exec.shutil, "which", lambda _name: None)
|
|
|
|
assert code_exec._resolve_python_bin(sandbox_enabled=False) == str(python_bin)
|
|
|
|
|
|
def test_code_exec_prefers_current_interpreter_for_non_bubblewrap_sandbox(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
) -> None:
|
|
python_bin = tmp_path / ("python.exe" if os.name == "nt" else "python")
|
|
python_bin.write_text("", encoding="utf-8")
|
|
python_bin.chmod(python_bin.stat().st_mode | stat.S_IXUSR)
|
|
monkeypatch.setattr(sys, "executable", str(python_bin))
|
|
monkeypatch.setattr(code_exec.shutil, "which", lambda _name: None)
|
|
monkeypatch.setattr(
|
|
code_exec,
|
|
"get_runtime",
|
|
lambda: SimpleNamespace(backend=SimpleNamespace(name="noop")),
|
|
)
|
|
|
|
assert code_exec._resolve_python_bin(sandbox_enabled=True) == str(python_bin)
|
|
|
|
|
|
def test_code_exec_bubblewrap_sandbox_prefers_visible_system_python(
|
|
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
|
|
) -> None:
|
|
host_python = tmp_path / ("venv-python.exe" if os.name == "nt" else "venv-python")
|
|
sandbox_python = tmp_path / ("python3.exe" if os.name == "nt" else "python3")
|
|
host_python.write_text("", encoding="utf-8")
|
|
sandbox_python.write_text("", encoding="utf-8")
|
|
host_python.chmod(host_python.stat().st_mode | stat.S_IXUSR)
|
|
sandbox_python.chmod(sandbox_python.stat().st_mode | stat.S_IXUSR)
|
|
monkeypatch.setattr(sys, "executable", str(host_python))
|
|
monkeypatch.setattr(code_exec.shutil, "which", lambda _name: None)
|
|
monkeypatch.setattr(code_exec, "_SANDBOX_PYTHON_CANDIDATES", (sandbox_python,))
|
|
monkeypatch.setattr(
|
|
code_exec,
|
|
"get_runtime",
|
|
lambda: SimpleNamespace(backend=SimpleNamespace(name="bubblewrap")),
|
|
)
|
|
|
|
assert code_exec._resolve_python_bin(sandbox_enabled=True) == str(sandbox_python)
|
|
|
|
|
|
def test_code_exec_allows_active_workspace_under_sensitive_parent(
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
workspace = tmp_path / "workspace"
|
|
workspace.mkdir()
|
|
monkeypatch.setattr(sensitive_paths, "_SENSITIVE_PREFIXES", (str(tmp_path),))
|
|
monkeypatch.setattr(
|
|
sensitive_paths,
|
|
"_WORKSPACE_PARENT_EXCEPTION_MARKERS",
|
|
(str(tmp_path),),
|
|
)
|
|
token = current_tool_context.set(ToolContext(workspace_dir=str(workspace)))
|
|
try:
|
|
result = code_exec._check_code_sensitive_access(
|
|
f"from pathlib import Path\nprint(Path({str(workspace / 'data.txt')!r}).read_text())"
|
|
)
|
|
finally:
|
|
current_tool_context.reset(token)
|
|
|
|
assert result is None
|
|
|
|
|
|
def test_code_exec_workspace_exception_keeps_leaf_secret_blocks(
|
|
tmp_path: Path,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
workspace = tmp_path / "workspace"
|
|
workspace.mkdir()
|
|
monkeypatch.setattr(sensitive_paths, "_SENSITIVE_PREFIXES", (str(tmp_path),))
|
|
monkeypatch.setattr(
|
|
sensitive_paths,
|
|
"_WORKSPACE_PARENT_EXCEPTION_MARKERS",
|
|
(str(tmp_path),),
|
|
)
|
|
token = current_tool_context.set(ToolContext(workspace_dir=str(workspace)))
|
|
try:
|
|
result = code_exec._check_code_sensitive_access(
|
|
f"open({str(workspace / '.env')!r}).read()"
|
|
)
|
|
finally:
|
|
current_tool_context.reset(token)
|
|
|
|
assert result is not None
|
|
assert result[0] == "sensitive_path"
|