> ## Documentation Index
> Fetch the complete documentation index at: https://codexceed.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# avatar.sandbox

Hermetic execution at the command seam (ADR-0042).

Every command the harness runs — the verifier's frozen checks *and* the model's
`run_command` — funnels through `Workspace._run_unlogged`. A `Sandbox` transforms
that one call: it computes the environment the child runs under and (in the OS/
container backends) wraps the argv in a launcher that denies network and confines
writes. It never *runs* the command — the `Workspace` still does — so the seam
stays a single chokepoint and `prepare()` is a pure transform (design invariant #5).

Scope is **Threat C only** (ADR-0042): it closes runtime/substrate gaming — an
inherited `PYTEST_ADDOPTS`/`PYTHONPATH`, a phone-home, a fork bomb — not a model
that authors weak tests (Threat B) or guts the graded ones (Threat A). Workspace-
*discovered* config (`conftest.py`, `pyproject` addopts) is a file, not env, and is
out of scope here by decision (the adequacy/diff-scope lever, ADR-0040).

Backends, weakest→strongest, all behind the same `prepare()`:

* `none` — identity argv + the full inherited environment (today's behavior; the
  back-compat escape hatch).
* `hermetic-env` — identity argv + an env scrubbed to a language-neutral allowlist,
  so `PYTEST_ADDOPTS`/`NODE_OPTIONS`/`RUBYOPT`/`PYTHONPATH`/`CLASSPATH` vanish *by
  construction* (no per-language whack-a-mole). The portable floor: pure Python,
  every OS, no dependencies. **The default.**
* `sandbox-exec` — the allowlisted env + argv wrapped in the macOS launcher with a
  network-deny profile (Apple-deprecated, an optional native fast-path).
* `bwrap` — Linux bubblewrap: the allowlisted env + a read-only root with only the
  workspace writable + a network namespace unshared (Increment 2).
* `container` — a Podman/Docker run: net-deny, read-only rootfs with the workspace
  bind-mounted writable, a clean env, kernel-enforced pid cap. The one genuinely
  cross-platform strong sandbox (Increment 2); needs the runtime + an image.

Resource limits (`RLimits`) ride `ExecSpec.preexec_fn` for the direct-exec backends
and container flags for the container backend. They ship **off by default**:
`preexec_fn` runs between `fork` and `exec`, which is not thread-safe against the
multithreaded eval runner (ADR-0026), so they are an opt-in toggle, not baked into
the default.

## Classes

### `Bwrap`

`bwrap` (Linux): a bubblewrap sandbox — read-only root, writable workspace, no network.

The Linux-native strong backend (ADR-0042 Increment 2). Binds the whole root read-only,
re-binds the workspace writable, mounts a fresh `/tmp`, and (unless network is allowed)
unshares the network namespace. The env is allowlist-scrubbed via the child's inherited
environment (no `--clearenv` needed — `subprocess` sets it).

Args:
allow\_network: When `True`, keep the network namespace (no `--unshare-net`).
rlimits: Optional resource ceilings applied via `preexec_fn` (opt-in; see `RLimits`).

```python theme={null}
Bwrap(*, allow_network: 'bool' = False, rlimits: 'RLimits | None' = None) -> 'None'
```

#### `Bwrap.prepare(self, argv: 'list[str]', cwd: 'Path') -> 'ExecSpec'`

Wrap `argv` in bubblewrap with `cwd` the only writable path.

Args:
argv: The command's argument vector.
cwd: The workspace root, re-bound writable inside the otherwise read-only sandbox.

Returns:
An `ExecSpec` whose argv is the `bwrap` invocation, under the scrubbed environment.

### `Container`

`container`: a Podman/Docker run — the cross-platform strong sandbox (ADR-0042 Increment 2).

Net-denied by default, a read-only rootfs with the workspace bind-mounted writable at
`/workspace`, a fresh tmpfs `/tmp`, and a kernel-enforced pid cap. The guest env is the
image's own toolchain plus only the portable vars forwarded via `-e` — the host `PATH`/
`VIRTUAL_ENV` are meaningless inside and are not passed. Needs the runtime on `PATH` and
an image carrying the task's toolchain.

Args:
image: The container image (e.g. `docker.io/library/python:3.12-slim`).
runtime: The container CLI (`podman` or `docker`).
allow\_network: When `True`, use `--network bridge` instead of `--network none`.
rlimits: Resource ceilings; the pid cap is always applied, CPU/FSIZE are guest-managed.

```python theme={null}
Container(*, image: 'str', runtime: 'str' = 'podman', allow_network: 'bool' = False, rlimits: 'RLimits | None' = None) -> 'None'
```

#### `Container.prepare(self, argv: 'list[str]', cwd: 'Path') -> 'ExecSpec'`

Wrap `argv` in a `podman run` (or `docker run`) with the workspace bind-mounted.

Args:
argv: The command's argument vector, run as the container's command.
cwd: The workspace root, bind-mounted read-write at `/workspace`.

Returns:
An `ExecSpec` whose argv is the container-runtime invocation; its own env is the
host environment (so the runtime CLI resolves), while the guest env is set via `-e`.

### `ExecSpec`

What to exec and under what environment — the pure output of `Sandbox.prepare`.

A small spec rather than a bare `(argv, env)` tuple because resource limits can't be
expressed as env: `preexec_fn` carries POSIX child setup for the backends that use it.
The `Workspace` executes this; the sandbox never does.

Args:
argv: The argument vector to actually exec (identity, or launcher-wrapped).
env: The complete environment the child runs under (never inherited implicitly).
preexec\_fn: Optional POSIX child setup (resource limits); `None` for the env-only
backends, which keeps execution thread-safe (see `RLimits`).

```python theme={null}
ExecSpec(argv: 'list[str]', env: 'dict[str, str]', preexec_fn: 'Callable[[], None] | None' = None) -> None
```

### `HermeticEnv`

`hermetic-env`: identity argv + an allowlist-scrubbed environment (the portable default).

Closes the env-injection sub-route of Threat C on every OS with no dependencies. It does
*not* deny network (no OS mechanism at this layer) — that needs `sandbox-exec`/`bwrap`/
`container`.

Args:
rlimits: Optional resource ceilings applied via `preexec_fn` (opt-in; see `RLimits`).

```python theme={null}
HermeticEnv(*, rlimits: 'RLimits | None' = None) -> 'None'
```

#### `HermeticEnv.prepare(self, argv: 'list[str]', cwd: 'Path') -> 'ExecSpec'`

Return `argv` unchanged under an allowlist-scrubbed environment.

Args:
argv: The command's argument vector.
cwd: The working directory (unused — this backend transforms only the environment).

Returns:
An `ExecSpec` with `argv` verbatim and the environment filtered to the allowlist.

### `NoSandbox`

`none`: identity — the full inherited environment, exactly today's behavior (escape hatch).

```python theme={null}
NoSandbox()
```

#### `NoSandbox.prepare(self, argv: 'list[str]', cwd: 'Path') -> 'ExecSpec'`

Return `argv` unchanged under the full inherited environment.

Args:
argv: The command's argument vector.
cwd: The working directory (unused — identity backend imposes no confinement).

Returns:
An `ExecSpec` with `argv` verbatim and the whole `os.environ`.

### `RLimits`

POSIX resource ceilings a backend imposes on the child (ADR-0042 Increment 2).

Off by default (opt-in): applied via `preexec_fn` for the direct-exec backends, which
is not thread-safe between `fork` and `exec` against the multithreaded eval runner
(ADR-0026). Best-effort — a limit that cannot be lowered is skipped, never a crash.

Args:
cpu\_seconds: RLIMIT\_CPU ceiling (CPU-seconds) — a runaway loop is killed.
fsize\_bytes: RLIMIT\_FSIZE ceiling — a command cannot fill the disk.
pids: The container pid cap (`--pids-limit`) — a fork bomb cannot wedge the host.

```python theme={null}
RLimits(cpu_seconds: 'int' = 300, fsize_bytes: 'int' = 536870912, pids: 'int' = 1024) -> None
```

#### `RLimits.preexec(self) -> 'Callable[[], None] | None'`

Return a child-setup callable that lowers CPU/FSIZE limits, or `None` off-POSIX.

Returns:
A no-arg callable for `subprocess`' `preexec_fn`, or `None` when `resource` is
unavailable (non-POSIX).

### `Sandbox`

Transforms a command invocation for hermetic execution (ADR-0042); never runs it.

```python theme={null}
Sandbox(*args, **kwargs)
```

#### `Sandbox.prepare(self, argv: 'list[str]', cwd: 'Path') -> 'ExecSpec'`

Return the `ExecSpec` the `Workspace` should exec for `argv` under `cwd`.

Args:
argv: The command's argument vector (post `shlex.split`).
cwd: The workspace root the command runs in.

Returns:
The transformed `ExecSpec` (argv, environment, optional child setup).

### `SandboxExec`

`sandbox-exec` (macOS): allowlisted env + argv wrapped in the launcher, network denied.

Increment 1 confines the *network* only; write-confinement is deferred to the container
backend (Increment 2), which does it cleanly with a read-only rootfs — macOS write
profiles are finicky and the launcher itself is Apple-deprecated (kept as a native
fast-path, never the sole backend, ADR-0042).

Args:
allow\_network: When `True`, skip the wrap and run env-scrubbed only (network open).
rlimits: Optional resource ceilings applied via `preexec_fn` (opt-in; see `RLimits`).

```python theme={null}
SandboxExec(*, allow_network: 'bool' = False, rlimits: 'RLimits | None' = None) -> 'None'
```

#### `SandboxExec.prepare(self, argv: 'list[str]', cwd: 'Path') -> 'ExecSpec'`

Return the allowlisted env with `argv` wrapped in the launcher (unless network is allowed).

Args:
argv: The command's argument vector.
cwd: The working directory (unused — Increment 1 confines network, not writes).

Returns:
An `ExecSpec` under the scrubbed environment: `argv` verbatim when network is allowed,
else wrapped in `sandbox-exec` with a network-deny profile.

## Functions

### `hermetic_env(source: 'Mapping[str, str]') -> 'dict[str, str]'`

Filter `source` to the language-neutral allowlist — the portability trick (ADR-0042).

Dropping everything unlisted removes env-based rigging for *every* language at once,
rather than blocklisting each runtime's injection var. `PATH`/`VIRTUAL_ENV` survive so
legitimate verification (`python -m pytest`, `py_compile`) still resolves the interpreter.

Args:
source: The environment to filter (usually `os.environ`).

Returns:
A new dict holding only the allowlisted keys (exact names + `LC_*`).

### `make_sandbox(mode: 'str', *, allow_network: 'bool' = False, rlimits: 'RLimits | None' = None, image: 'str' = '', runtime: 'str' = 'podman') -> 'Sandbox'`

Construct the `Sandbox` for a config `sandbox_mode` (ADR-0042).

Args:
mode: One of `none` / `hermetic-env` / `sandbox-exec` / `bwrap` / `container`.
allow\_network: Passed to the OS/container backends; ignored by `none`/`hermetic-env`,
which cannot gate network at their layer.
rlimits: Optional resource ceilings (opt-in; ignored by `none`).
image: The container image — required when `mode == "container"`.
runtime: The container CLI for `mode == "container"` (`podman` or `docker`).

Returns:
The matching `Sandbox`.

Raises:
ValueError: For an unknown mode, or `container` without an image.
