Skip to content

apomesh-substrate-sandbox

apomesh-substrate-sandbox is a substrate implementation plane: it owns confinement for both execution tiers, and owning both in one crate is the point — it is what lets the two share primitives instead of each growing its own half-correct copy. Sandbox-by-default is a non-negotiable substrate guarantee, with no per-tool “trusted” escape hatch. This crate owns how isolation is applied; the port traits, the policy vocabulary, and the contract itself live in apomesh-substrate-types.

The tiers are distinguished by the unit of execution, never by the confinement technology — a new technology enters as an adapter within a tier:

TierUnitContractBoot-selected backends
1 — tool sandboxa declared toolSandboxStrategyBubblewrap + seccomp (Linux), sandbox-exec (macOS), NoOp (test only)
2 — workload runtimean OCI imageRuntimeExecutorEmbeddedOci (youki libcontainer)

Tier 2 is what runs a programmable agent: a long-lived confined workload with a framed bidirectional channel and a resource envelope, rather than a short-lived request/response command. Keeping the two contracts distinct is deliberate — folding a long-lived channel into a wrap-a-command interface would be the wrong reuse.

Touch it for isolation mechanics: a new platform adapter, a new runtime backend, the runner wire framing, or the boot-time selection posture.

  • Layer: substrate implementation plane. See Workers — the sandbox isolation chain.
  • Depends on: apomesh-substrate-types (the ToolSandbox port plus the SandboxPolicy / SandboxError vocabulary it implements), and the platform-gated libc / seccompiler trees the dependency-light vocabulary crate deliberately excludes.
  • Consumed by: apomesh-substrate (which re-exports the plane as apomesh_substrate::tool_sandbox), apomesh-substrate-tools (whose shell tools compose the shell-exec spawner), and apomesh-substrate-mcp (which spawns stdio MCP servers as long-lived sandboxed subprocesses).
  • The per-OS ToolSandbox adaptersBubblewrapSandbox on Linux (bubblewrap namespaces plus a per-category seccomp-BPF program compiled in-process by seccompiler and handed to bwrap via --seccomp) and SandboxExecSandbox on macOS (sandbox-exec with a generated SBPL profile). Each is compile-gated to its platform; the impl module cannot be referenced off-platform.
  • The runner-subprocess contract — a sandboxed dispatch spawns an apomesh-tool-runner child and exchanges 4-byte length-prefixed JSON frames (ToolInput in on stdin, ToolOutput out on stdout). runner_io owns the shared framing, the exit-code vocabulary, and the signal mapping both adapters reuse; per-OS signal classification stays in each adapter.
  • Boot-time selection, fail-closedselect_sandbox_from_env resolves APOMESH_SANDBOX (defaulting per platform) into an Arc<dyn ToolSandbox>. An unknown value, an unsupported platform, or a release-build no-op request each surface a typed SandboxSelectionError at startup rather than a mid-dispatch panic.
  • The shell-exec sandboxSandboxedCommand wraps arbitrary agent-supplied shell / CLI commands (a plane independent of the runner path) under the same per-OS engines. Secure-by-default: an unset APOMESH_SHELL_SANDBOX fails closed in a release build; an explicit none is honored and loudly warned only where the surrounding container is itself the isolation boundary.
  • Subprocess env hygiene — every spawn runs env_clear() then re-adds only the narrow PASS_THROUGH_ENV allowlist before injecting operator-declared secrets, so ambient host provider keys never reach a sandboxed child; injected-secret cleartext is redacted from captured output at the spawn boundary.

It does not own the tool implementations (those live in apomesh-substrate-tools), the runner binary (its own apomesh-tool-runner crate), or the ToolSandbox port and its SandboxPolicy / SandboxError vocabulary (defined in apomesh-substrate-types and re-exported flat here).

  • select_sandbox_from_env — resolve APOMESH_SANDBOX (or the per-platform default) into a working Arc<dyn ToolSandbox>; the worker’s boot entry point.
  • SandboxSelection — the closed enum of supported impls (Bubblewrap / SandboxExec / NoOpTestOnly); a new variant forces an explicit selection arm.
  • SandboxSelectionError — startup-time selection failures (unknown value, no platform default, build-configuration refusal, construction failure), kept distinct from the runtime SandboxError.
  • BubblewrapSandbox (Linux) — the bubblewrap + seccomp-BPF adapter.
  • SandboxExecSandbox (macOS) — the sandbox-exec + SBPL adapter.
  • SandboxedCommand + SandboxStrategy — the shell-exec spawner and its per-OS strategy; SHELL_SANDBOX_ENV names the selecting variable.
  • locate_tool_runner — resolve the apomesh-tool-runner binary (env override → PATH → sibling of the current exe).
  • NoOpSandbox / FirecrackerSandbox — test-only stubs behind the test-util feature; NoOpSandbox::new panics in a release build.

The port types (ToolSandbox, SandboxPolicy, policy_for, LongLivedSpec, …) are re-exported from apomesh-substrate-types; see its page for their contracts.

A deployment selects its sandbox by environment variable — the worker calls select_sandbox_from_env at startup, and the shell tools call SandboxedCommand::from_env:

Terminal window
# Runner-path sandbox for Tool::dispatch. Unset → per-platform default
# (bubblewrap on Linux, sandbox-exec on macOS).
export APOMESH_SANDBOX=sandbox-exec
# Shell-exec sandbox for agent-supplied shell / CLI commands. Unset fails
# CLOSED in a release build; `none` is honored only where the surrounding
# container is itself the isolation boundary (local dev).
export APOMESH_SHELL_SANDBOX=none

Both selectors are fail-closed: an unknown value or an unsupported platform is a typed startup error, and the noop-test-only sandbox is compiled only under the test-util feature and refuses to construct in a release build. No runtime flag bypasses the sandbox.

  • Concepts: Workers (the sandbox-by-default isolation chain in the execution plane), The credential plane (the env_clear + allowlist boundary and how a resolved secret is injected at the sandbox edge).
  • Reference: apomesh-substrate-types (the ToolSandbox port this plane implements), apomesh-worker (the layer that selects and drives the sandbox at dispatch).