Linux sandbox lacks an actionable diagnostic when bwrap is blocked and Landlock is unavailable

Open 💬 0 comments Opened Jul 27, 2026 by chengcuiping

What version of Codex CLI is running?

codex-cli 0.145.0

What subscription do you have?

Pro

Which model were you using?

N/A — the failure occurs during local sandbox startup, before a model-generated command can execute.

What platform is your computer?

Linux 5.4.0-171-generic x86_64 x86_64

What terminal emulator and version are you using (if applicable)?

Browser-based Jupyter terminal running in a Kubernetes/containerd container.

Codex doctor report

Not available — codex doctor --json was not captured before the
reproducing node was replaced. The replacement node does not have
Codex installed, so its doctor report would not describe the
reproducing environment.

What issue are you seeing?

Codex cannot start either Linux sandbox backend in this restricted container environment.

The default Bubblewrap backend fails because mount namespace and mount propagation operations are denied by the container/AppArmor policy:

bwrap: Failed to make / slave: Permission denied

The legacy Landlock backend also fails:

error applying legacy Linux sandbox restrictions:
Sandbox(LandlockRestrict)

The host is running Linux 5.4, which predates Landlock support. The environment may therefore be incapable of supporting either safe sandbox backend.

The issue being reported is the error handling and diagnostics: Codex shows a low-level Bubblewrap error, while the Landlock path terminates with a Rust panic. It does not clearly explain that neither safe sandbox
backend is available or state the host requirements needed to resolve the problem.

### What steps can reproduce the bug?

Thread ID: N/A — reproduced directly with `codex sandbox linux`,
outside an interactive Codex thread.

Environment:

- Codex CLI: `0.145.0`
- Bubblewrap: `0.9.0`
- Kernel: `5.4.0-171-generic`
- Architecture: `x86_64`
- AppArmor profile: `cri-containerd.apparmor.d (enforce)`
- Root mount propagation: `private,slave`

Run:

```bash
unshare --user --map-root-user true
echo $?

Result:

0

Run:

unshare --user --map-root-user --mount \
    sh -c 'mount --make-rslave /'

Result:

unshare: cannot change root filesystem propagation: Permission denied

Run:

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

Result:

bwrap: Creating new namespace failed: Operation not permitted

Run the default Codex sandbox:

codex sandbox linux -- /bin/true

Result:

bwrap: Failed to make / slave: Permission denied

Run the legacy Landlock sandbox:

codex \
    -c 'features.use_legacy_landlock=true' \
    sandbox linux -- /bin/true

Result:

thread 'main' panicked at linux-sandbox/src/linux_run_main.rs:
error applying legacy Linux sandbox restrictions:
Sandbox(LandlockRestrict)

### What is the expected behavior?

Codex should detect that neither safe Linux sandbox backend is
available and exit cleanly with an actionable diagnostic.

The diagnostic should state that:

- Bubblewrap cannot operate because mount namespace operations are
  denied by the container/AppArmor policy.
- Landlock is unavailable on the running kernel.
- `workspace-write` and `read-only` sandbox execution cannot start
  until the host or container configuration is changed.

The Landlock path should return a normal error rather than a Rust panic.
Codex should not automatically fall back to unrestricted execution.

### Additional information

Related issues:

- #15434 and #23468 report the same Bubblewrap
  `Failed to make / slave` error, but Landlock worked in those
  environments.
- #29908 covers related AppArmor/user-namespace failures with different
  Bubblewrap errors.
- #34008 covers both sandbox backends being unavailable for a different
  `pivot_root` cause.

This case differs from #15434 and #23468 because Bubblewrap is blocked
by the container policy while Landlock cannot serve as a fallback on
the Linux 5.4 host.

This report is specifically about preflight detection, actionable error
reporting, and avoiding the Rust panic. It is not requesting that Codex
bypass AppArmor or silently fall back to unrestricted execution.

View original on GitHub ↗