Skip to main content

Module sandbox

Module sandbox 

Source
Expand description

Sandbox — a generic, process-wide execution boundary (Linux only).

This is not a policy engine. There are no per-bridge rules, no domain allowlists and no dynamic decisions: the sandbox installs one coarse OS-level boundary around the whole process, once, at startup. Everything the process does afterwards — sh.exec, mcp.connect child processes, Lua io.*/os.*, the HTTP client — runs inside that boundary because Landlock rulesets and seccomp filters are inherited across fork(2) / execve(2).

§What is enforced

AxisBehaviour
read / executeunrestricted (/ is granted ReadFile/ReadDir/Execute)
writedenied except for an explicit allowlist (see below)
TCPunrestricted by default; tcp = false denies bind+connect
io_uringio_uring_setup / io_uring_enter / io_uring_register fail with EPERM

Reads and executes are deliberately left open so that PATH lookups, shared library loading and ordinary tooling keep working — the boundary is about mutation, not secrecy.

The write allowlist is:

  • the project root (--project),
  • the agent-block state dir (AGENT_BLOCK_HOME, default $HOME/.agent-block),
  • /tmp,
  • /dev/null, /dev/urandom, /dev/tty,
  • every path listed in AGENT_BLOCK_SANDBOX_FS_RW (:-separated).

Entries that do not exist are skipped rather than treated as an error, so a shared config can list paths that are only present on some machines.

io_uring is blocked because it lets a task submit file and socket operations through a shared ring, bypassing the syscall-level view a seccomp filter has. Landlock still covers ring-submitted filesystem operations, but denying the setup syscall keeps the boundary easy to reason about.

§Failure model

Fail-closed: when the sandbox is requested but the kernel enforces nothing (no Landlock support), apply returns an error and the caller is expected to abort startup. A partial enforcement of the default rights (older Landlock ABI, e.g. no Truncate) logs a warn! describing what was dropped and continues — the filesystem boundary is still real in that case. Two things are never downgraded to a warning: an unresolvable project root (the primary write grant) and an explicitly requested TCP denial on a kernel whose Landlock ABI predates network rights — both abort startup.

§KNOWN LIMITATIONS

  • Linux only. On other platforms apply returns SandboxError::Unsupported; there is no silent no-op.
  • UDP and DNS are not restricted. Landlock’s network rights cover TCP bind/connect only, so tcp = false does not stop UDP traffic (including DNS resolution) or unix-domain sockets.
  • io_uring is unusable inside the sandbox, including for dependencies that would otherwise opportunistically use it.
  • TCP is a single on/off switch. There is no per-host or per-port granularity, by design — that would be policy, not a boundary.
  • The boundary is process-wide and irreversible. It cannot be relaxed later in the process lifetime, and it must be installed before any thread that needs to be covered is spawned (Landlock’s restrict_self applies to the calling thread and its future children).
  • The io_uring deny only exists on x86_64 and aarch64. On other Linux architectures no seccomp filter is compiled and the deny is skipped with a warn!; the Landlock filesystem boundary still applies there.

Structs§

SandboxConfig
Resolved sandbox knobs.

Enums§

SandboxError
Errors returned by apply.

Functions§

apply
Install the execution boundary for this process.