40 lines
1.2 KiB
Python
40 lines
1.2 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
|
|
class ToolSandbox:
|
|
"""Applies simple working directory and timeout restrictions."""
|
|
|
|
def __init__(self, allowed_root: str | Path, timeout_ms: int) -> None:
|
|
self._allowed_root = Path(allowed_root).resolve()
|
|
self._timeout_seconds = max(timeout_ms / 1000, 1)
|
|
|
|
def ensure_path_allowed(self, path: str | Path) -> Path:
|
|
resolved = Path(path).expanduser().resolve()
|
|
# Permission-first model: path is allowed if it exists
|
|
# Permission service will handle write/shell restrictions
|
|
return resolved
|
|
|
|
def run_shell(
|
|
self,
|
|
command: str,
|
|
cwd: str | Path | None = None,
|
|
stdin_data: str | None = None,
|
|
) -> subprocess.CompletedProcess[str]:
|
|
working_directory = self.ensure_path_allowed(cwd or self._allowed_root)
|
|
env = {"PATH": os.environ.get("PATH", "")}
|
|
return subprocess.run(
|
|
command,
|
|
shell=True,
|
|
cwd=str(working_directory),
|
|
env=env,
|
|
text=True,
|
|
capture_output=True,
|
|
input=stdin_data,
|
|
timeout=self._timeout_seconds,
|
|
check=False,
|
|
)
|