feat: pin bwrap rein runtimes and isolate private state
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0726e-5232-73f2-aaca-2c05ceb62efb
This commit is contained in:
parent
c2886b2f77
commit
d69827aaa2
12 changed files with 639 additions and 9 deletions
|
|
@ -15,6 +15,7 @@ from pathlib import Path
|
|||
from typing import Any
|
||||
|
||||
from sandboxer.extensions.base import SandboxExtension
|
||||
from sandboxer.extensions.runtime import RUNTIME_MOUNT, verified_runtime
|
||||
from sandboxer.models import Profile
|
||||
|
||||
|
||||
|
|
@ -72,6 +73,13 @@ class BwrapExtension(SandboxExtension):
|
|||
runner = Path(__file__).with_name("bwrap_runner.py")
|
||||
argv += ["--dir", "/run", "--dir", "/run/sandboxer"]
|
||||
argv += ["--ro-bind", str(runner), "/run/sandboxer/bwrap_runner.py"]
|
||||
runtime = verified_runtime(self.config)
|
||||
if runtime is not None:
|
||||
workspace = Path(workspace_dir).resolve()
|
||||
if runtime.is_relative_to(workspace) or workspace.is_relative_to(runtime):
|
||||
raise ValueError("runtime and workspace must not overlap")
|
||||
argv += ["--dir", "/opt", "--dir", "/opt/sandboxer"]
|
||||
argv += ["--ro-bind", str(runtime), RUNTIME_MOUNT]
|
||||
argv += ["--bind", workspace_dir, workspace_dir]
|
||||
argv += ["--chdir", workspace_dir]
|
||||
argv += [
|
||||
|
|
@ -80,6 +88,8 @@ class BwrapExtension(SandboxExtension):
|
|||
workspace_dir,
|
||||
f"{workspace_dir}/{self.control_socket_name}",
|
||||
]
|
||||
if runtime is not None:
|
||||
argv.append("--runtime")
|
||||
return argv
|
||||
|
||||
@staticmethod
|
||||
|
|
@ -102,6 +112,15 @@ class BwrapExtension(SandboxExtension):
|
|||
def provision(
|
||||
self, profile: Profile, inputs: dict[str, str], host: str
|
||||
) -> dict[str, str]:
|
||||
if profile.network.default != "deny" or profile.network.egress:
|
||||
raise ValueError("bwrap currently supports only default-deny with empty egress")
|
||||
if profile.setup.secret_refs:
|
||||
raise ValueError("bwrap has no setup credential delivery contract")
|
||||
runtime = verified_runtime(self.config)
|
||||
if runtime is not None and inputs.get("repo"):
|
||||
source = Path(inputs["repo"]).resolve()
|
||||
if source.is_relative_to(runtime) or runtime.is_relative_to(source):
|
||||
raise ValueError("runtime and source checkout must not overlap")
|
||||
sandbox_id = self.new_sandbox_id(inputs)
|
||||
workspace_dir = f"{self.base_dir}/{sandbox_id}"
|
||||
Path(workspace_dir).mkdir(parents=True, exist_ok=True)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue