Skip to main content

Module isolation

Module isolation 

Source
Expand description

Stage execution isolation.

Wraps subprocess execution in a sandbox that restricts what the stage can read, write, and call. Closes the gap documented in SECURITY.md: a user-authored Python stage has host-user privileges by default; with isolation it runs in a bounded filesystem + network namespace.

Phase 1 (v0.7) backends:

  • IsolationBackend::None — legacy pass-through. Emits a warning unless the user opts in with --unsafe-no-isolation / NOETHER_ISOLATION=none.
  • IsolationBackend::Bwrap — bubblewrap wrapper. Linux-only. Requires the bwrap binary in PATH.

Phase 2 (v0.8) will add IsolationBackend::Native — direct unshare(2) + Landlock + seccomp syscalls, no external binary. See docs/roadmap/2026-04-18-stage-isolation.md.

§Policy derivation

An IsolationPolicy is derived from a stage’s declared EffectSet. Phase 1 surfaces exactly one axis from the effect vocabulary — Effect::Network toggles whether the sandbox inherits the host’s network namespace. Every other effect variant (Pure, Fallible, Llm, NonDeterministic, Process, Cost, Unknown) produces the same baseline policy: RO /nix/store bind, a sandbox-private /work tmpfs, --cap-drop ALL, UID/GID mapped to nobody, --clearenv with a short allowlist.

§TLS trust store — dual path

When network=true, the sandbox binds /etc/ssl/certs (via --ro-bind-try) for non-Nix-aware clients that expect the system trust store (curl, openssl). Nix-built code uses NIX_SSL_CERT_FILE / SSL_CERT_FILE (both in the env allowlist) pointing into /nix/store, which is always bound. So TLS works whether the stage resolves certs through the filesystem path or the env-pointer path; NixOS hosts without /etc/ssl/certs fall through to the env path automatically.

§Filesystem effects — not yet expressible

The v0.6 Effect enum has no FsRead(path) / FsWrite(path) variants, so there is no way for a stage to declare “I need to read /etc/ssl but nothing else.” The sandbox compensates by allowing nothing outside /nix/store, the executor’s cache dir, and the nix binary. That is the strictest sane default — but it means stages that legitimately need a specific host path cannot run under isolation today. Planned for v0.8: extend Effect with FsRead / FsWrite path variants, then expand from_effects to translate them into bind mounts. Tracked in docs/roadmap/2026-04-18-stage-isolation.md.

Structs§

IsolationPolicy
What the sandbox does and doesn’t let a stage reach.

Enums§

IsolationBackend
Which isolation backend to use for a stage execution.
IsolationError
Error from the isolation layer itself — policy misconfiguration or backend unavailable. Stage-body errors come back as the usual ExecutionError on the inner command.

Functions§

build_bwrap_command
Build a bwrap invocation that runs cmd inside a sandbox.
find_bwrap
Locate the bwrap binary.