mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-04-08 04:03:38 +00:00
50 lines
1.7 KiB
Python
50 lines
1.7 KiB
Python
"""Sandbox backends for shell command execution.
|
|
|
|
To add a new backend, implement a function with the signature:
|
|
_wrap_<name>(command: str, workspace: str, cwd: str) -> str
|
|
and register it in _BACKENDS below.
|
|
"""
|
|
|
|
import shlex
|
|
from pathlib import Path
|
|
|
|
|
|
def _bwrap(command: str, workspace: str, cwd: str) -> str:
|
|
"""Wrap command in a bubblewrap sandbox (requires bwrap in container).
|
|
|
|
Only the workspace is bind-mounted read-write; its parent dir (which holds
|
|
config.json) is hidden behind a fresh tmpfs.
|
|
"""
|
|
ws = Path(workspace).resolve()
|
|
try:
|
|
sandbox_cwd = str(ws / Path(cwd).resolve().relative_to(ws))
|
|
except ValueError:
|
|
sandbox_cwd = str(ws)
|
|
|
|
required = ["/usr"]
|
|
optional = ["/bin", "/lib", "/lib64", "/etc/alternatives",
|
|
"/etc/ssl/certs", "/etc/resolv.conf", "/etc/ld.so.cache"]
|
|
|
|
args = ["bwrap", "--new-session", "--die-with-parent"]
|
|
for p in required: args += ["--ro-bind", p, p]
|
|
for p in optional: args += ["--ro-bind-try", p, p]
|
|
args += [
|
|
"--proc", "/proc", "--dev", "/dev", "--tmpfs", "/tmp",
|
|
"--tmpfs", str(ws.parent), # mask config dir
|
|
"--dir", str(ws), # recreate workspace mount point
|
|
"--bind", str(ws), str(ws),
|
|
"--chdir", sandbox_cwd,
|
|
"--", "sh", "-c", command,
|
|
]
|
|
return shlex.join(args)
|
|
|
|
|
|
_BACKENDS = {"bwrap": _bwrap}
|
|
|
|
|
|
def wrap_command(sandbox: str, command: str, workspace: str, cwd: str) -> str:
|
|
"""Wrap *command* using the named sandbox backend."""
|
|
if backend := _BACKENDS.get(sandbox):
|
|
return backend(command, workspace, cwd)
|
|
raise ValueError(f"Unknown sandbox backend {sandbox!r}. Available: {list(_BACKENDS)}")
|