Skip to main content

Crate noether_isolation

Crate noether_isolation 

Source
Expand description

Stage execution isolation — the sandbox primitive extracted from [noether_engine::executor::isolation] for consumers that want isolation without pulling in the composition engine.

The noether-engine crate re-exports this module verbatim, so existing callers see no API change. Downstream consumers (agentspec, the standalone noether-sandbox binary) depend on this crate directly.

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.
RoBind
A single read-only bind mount. Named-struct rather than a tuple so the JSON wire format stays readable for non-Rust consumers: {"host": "/nix/store", "sandbox": "/nix/store"} instead of the earlier ["/nix/store", "/nix/store"]. The latter was terser but gave external language bindings no schema hint about which path was which.
RwBind
A single read-write bind mount. The exact counterpart of RoBind for the rw_binds field — same wire shape, same ergonomics, same From<(PathBuf, PathBuf)> convenience.

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 execution error on the inner command.

Constants§

NOBODY_GID
NOBODY_UID
Conventional “nobody” UID/GID on Linux. bwrap maps the invoking user to this identity inside the sandbox so the stage cannot observe the real UID of the caller.
TRUSTED_BWRAP_PATHS
Root-owned locations where bwrap lives on a correctly-provisioned Linux host. Order matters: NixOS system profile first (nix hosts almost always have this), then the Determinate / single-user nix profile, then distro-packaged /usr/bin, then manual installs.

Functions§

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