InitRunner

Runtime Sandbox

Since v2026.4.16, tool subprocesses run under kernel-level isolation, outside the initrunner process. This is distinct from the PEP 578 audit-hook sandbox (security.tools.audit_hooks_enabled), which runs inside the Python interpreter.

Pick one of two backends:

  • Bubblewrap — Linux user namespaces. No daemon, no Docker, no root. Default on Linux.
  • Docker Sandbox — Containers via the Docker daemon. Works on macOS, Windows, and Linux. Supports pinned images and bridge networking.

backend: auto tries bwrap on Linux and falls back to Docker. This page is the shared config reference; the linked pages cover each backend's details, examples, and limits.

Configuration

security:
  sandbox:
    backend: auto                 # auto | bwrap | docker | none (default: none)
    network: none                 # none | bridge | host
    allowed_read_paths: []
    allowed_write_paths: []
    memory_limit: "256m"
    cpu_limit: 1.0
    read_only_rootfs: true
    bind_mounts: []
    env_passthrough: []
    docker:
      image: "python:3.12-slim"
      user: "auto"
      extra_args: []

backend

ValueBehavior
noneNo isolation. Tool subprocesses run on the host.
bwrapBubblewrap (Linux only). Lightweight user-namespace sandbox.
dockerDocker container. Requires a running Docker daemon.
autoPrefers bwrap on Linux, falls back to Docker. Never falls to none.

network

Valuebwrapdocker
none--unshare-net (empty namespace)--network none
bridgeNot supported (raises error)--network bridge
hostHost network (no namespace)--network host

docker sub-config

  • image — Docker image (default python:3.12-slim).
  • user — Container user. "auto" maps to the current uid:gid when writable mounts exist. null runs as root.
  • extra_args — Additional docker run flags. The schema blocks dangerous flags such as --privileged and --cap-add.

Backends at a glance

bubblewrapDocker
PlatformLinux onlymacOS, Windows, Linux
DaemonNone (bwrap binary)Docker daemon required
Startup costfork+execve~200–500ms per call
FilesystemHost /usr, /bin, /lib bound read-onlyPinned image
Network isolation--unshare-net--network none
Bridge networkingNot supported--network bridge
Resource limitssystemd-run --user (skipped with a warning if unavailable)-m, --cpus, --pids-limit
Installapt install bubblewrapapt install docker.io or Docker Desktop

Mount validation

Mounts fall into two categories:

  • User-configured (allowed_read_paths, allowed_write_paths, bind_mounts from role YAML) — validated at load time against the role's permitted roots. A typo'd /etc mount fails before the role ever runs.
  • Tool-internal (e.g. python_exec writes code to /tmp and mounts it at /work/_run.py) — code-controlled, trusted, no validation.

Audit

Every sandboxed call logs a sandbox.exec security event:

FieldMeaning
backendwhich backend ran the command
argv0the command that ran
rcexit code
duration_mswall-clock time

Query with:

initrunner audit security-events --event-type sandbox.exec

Adaptive preflight

backend: auto and backend: bwrap run a functional probe before launching any tool:

bwrap --ro-bind /usr /usr -- /bin/true

If the probe fails, SandboxUnavailableError.remediation reads /proc/sys/kernel/unprivileged_userns_clone and /proc/sys/kernel/apparmor_restrict_unprivileged_userns and emits the specific fix — sysctl, AppArmor profile reinstall, or switch to backend: docker. The CLI renders the error as a clean Rich panel and exits with code 1.

initrunner doctor --role <file> now renders a sandbox row showing the resolved backend and readiness — Docker daemon reachable, bwrap probe passing, image pulled.

Migrating from security.docker

security.docker has been removed. A role still using it fails schema validation with migration instructions:

# Old (removed in v2026.4.16)
security:
  docker:
    enabled: true
    image: python:3.12-slim
    network: none

# New
security:
  sandbox:
    backend: docker
    network: none
    docker:
      image: python:3.12-slim

Bundle metadata

Published bundles declare supported_sandbox_backends in the manifest. initrunner install checks the host and warns when none of the listed backends is available. See OCI Distribution for the full manifest schema.

On this page