@rtq/sandbox
v0.1.1
Published
RTQ OS sandbox runtime: Seatbelt (macOS), bubblewrap (Linux), AppContainer+Job Object (Windows), fail-closed, with explicit enforcement reporting.
Maintainers
Readme
@rtq/sandbox
Real OS enforcement, not a policy suggestion. @rtq/sandbox runs a tool
inside a real OS backend on every major platform — bubblewrap (Linux),
Seatbelt (sandbox-exec, macOS), AppContainer+Job (Windows) — using
RTQ-derived allowlists, and returns an enforcement report the gateway can
prove in the audit trail (RTQ §46.21–46.22, §13).
The first principle here is §46.21 #1: RTQ will not execute a server's tool directly in-process "just this once" and hope; the tool either runs inside a real OS sandbox with an enforcement report, or RTQ records that this backend is not being enforced on this OS (explicit skip report, never a silent pass). Fail-closed, always.
What's inside
createSandbox(options)— returns aSandboxHandlefor a runtime built on one ofcreateDarwinSandbox(Seatbelt),createLinuxSandbox(bubblewrap), orcreateWindowsSandbox(AppContainer + Job object), selected from the runtime → backend mapping inSandboxRuntimeOptionsBackend/McpGatewayConfig.transportKind.buildBubblewrapArgs/buildSeatbeltArgs— construct the real backend argv in a new namespace: ro/rw bind mounts from RTQ allowlists only, no shared/dev(empty mount), private/tmp(tmpfs), no--share-netby default, bubbles apart from the host. Linux no-/usron Windows →SANDBOX_POLICY_INVALIDif the allowlist can't validate fail-closed (§46.21 #11,linux.test.ts#6).checkBwrapCapability/checkSeatbeltCapability— probe whether the real backend binary/sandbox-execexists before promising enforcement (construction invariants: never a silentfalse-positive "enforced").canonicalizePath/isPathAllowed/validateAllowlistPaths— path canonicalization + allowlist validation. A path that can't be canonicalized is denied, never guessed-as-abs (46.21 #8, #13).buildBubblewrapArgsrefusal is fail-closed: network allowlists that enforce only against the gateway (and not the OS) are refused at construction withSANDBOX_POLICY_INVALID, not silently downgraded (linux.test.ts"refuses network allowlists it cannot enforce").- Windows runner —
scripts/windows-runner.ps1shipped in-tree (noapprove=truebypass — CI greps and fails if a bypass appears). The note here: the Windows AppContainer is the REAL backend, andtests/sandbox/windows.test.tsdescribeMaybe-skips the Linux//usrtests so the suite works when the OS doesn't ship/usr.
Security invariants (tests/sandbox/* enforce on the real OS)
The sandbox suite (§46.21 #1–#14, §46.22 #1–#8, §13) is written to FAIL the pipeline when enforcement is missing:
- Real-OS test on each platform verifies the actual backend ran (file
effects landed in a private tmpfs, not the host); skip is explicit and
reported in CI (
sandbox.ymluploads an explicit skip suite provenance artifact), never a silent "¥passed". - The shipped
windows-runner.ps1is checked to contain noapprove=truesecret bypass and to exist on the Windows runner (real OS measure). buildBubblewrapArgsis namespace-safe by construction: it unshares user/PID/net/mount, binds only allowlisted paths, gives the process its own/dev//tmp, and — critically — never passes--share-net.
Note on platform truthfulness
Cross-platform CI (sandbox.yml) runs the enforcement suite on every OS
in the matrix. The Linux bubblewrap tests skip cleanly on Windows with a
reported skip (the OS deliberately can't prove /usr), so a red state means
"the backend is genuinely broken on this OS," never "the test file doesn't
exist for this platform."
License
Apache-2.0
