Voicebox documentation

Environment Sandboxing & Boundary Probes

Voicebox isolates execution environments using OS-level sandboxes and verifies every environment’s isolation boundaries by running an in-sandbox diagnostic probe (tools/sandbox-probe.mjs) rather than trusting static configuration labels.


1. Sandbox Isolation Tiers

Voicebox provides two Linux sandbox tiers for server environments:

  1. L1 — Bubblewrap Fence (tools/fence.sh):
    • Mounts /usr and /etc read-only (EROFS).
    • Mounts fresh tmpfs instances over /tmp, /run, /var, and /home.
    • Binds a single writable sandbox home directory from the host (VOICEBOX_SANDBOX_HOMES, default ~/sandbox-homes/<key>).
    • Isolates the process tree with --unshare-pid --die-with-parent.
  2. L1.5 — Systemd + Bubblewrap Composition (tools/fence-unit.sh, tools/voicebox-fence@.service):
    • Launches the L1 bubblewrap fence inside a transient systemd-run --user unit.
    • Enforces kernel syscall filtering (Seccomp: 2), drops all effective capabilities (CapEff: 0), enables PrivateTmp, and sets ProtectSystem=strict.
    • Enforces a finite unit lifetime (RuntimeMaxSec, default 1800s, configurable via VOICEBOX_FENCE_MAX_SEC). Units can be stopped explicitly via DELETE /api/environments/<key> (gated by x-voicebox-host-token) and are cleaned up automatically on server exit.

Explicit Non-Goals of L1 / L1.5


2. Fenced Command & Git Execution (tools/env-serve.mjs)

Each booted sandbox runs tools/env-serve.mjs on its loopback port, mediated by the local host (server.mjs):

Sandbox Endpoints

Host Proxy & Bearer Authentication


3. Earned Boundary Levels (measureBoundary)

When an environment boots, measureBoundary in lib/fence-provider.mjs evaluates the environment’s self-probe report (measuredBy: "probe") across four axes:

Verdict Meaning
fenced Probe measured the boundary and confirmed isolation holds.
not-fenced Probe measured the boundary and detected a violation (listed in violations).
passes Axis is intentionally shared (such as outbound network access).
not measured Probe did not measure this axis.

From these axis verdicts, measureBoundary derives the overall level:


4. Reading probe.json (GET /api/probe)

GET /api/probe runs tools/sandbox-probe.mjs inside the environment and caches the result at <workspace>/probe.json (mode 0600):


5. Key Implementation Files

Subsystem Files
L1 & L1.5 Sandbox Launchers tools/fence.sh, tools/fence-unit.sh, tools/voicebox-fence@.service
Diagnostic Probe & Cache tools/sandbox-probe.mjs, server.mjs (GET /api/probe)
Boundary Evaluation & Lifecycle lib/fence-provider.mjs, lib/unit-fence-provider.mjs
Fenced Server & Child Environment tools/env-serve.mjs, lib/fence-child-env.mjs
WebAssembly & Extension Gates lib/wasm-shelf.mjs, lib/wasm-worker.mjs, lib/extensions.mjs, core/extensions.ts