ducklm/app/tools/sandbox.py

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,
)