core-agent-ide/codex-rs/linux-sandbox
Michael Bolin 22ac6b9aaa
sandboxing: plumb split sandbox policies through runtime (#13439)
## Why

`#13434` introduces split `FileSystemSandboxPolicy` and
`NetworkSandboxPolicy`, but the runtime still made most execution-time
sandbox decisions from the legacy `SandboxPolicy` projection.

That projection loses information about combinations like unrestricted
filesystem access with restricted network access. In practice, that
means the runtime can choose the wrong platform sandbox behavior or set
the wrong network-restriction environment for a command even when config
has already separated those concerns.

This PR carries the split policies through the runtime so sandbox
selection, process spawning, and exec handling can consult the policy
that actually matters.

## What changed

- threaded `FileSystemSandboxPolicy` and `NetworkSandboxPolicy` through
`TurnContext`, `ExecRequest`, sandbox attempts, shell escalation state,
unified exec, and app-server exec overrides
- updated sandbox selection in `core/src/sandboxing/mod.rs` and
`core/src/exec.rs` to key off `FileSystemSandboxPolicy.kind` plus
`NetworkSandboxPolicy`, rather than inferring behavior only from the
legacy `SandboxPolicy`
- updated process spawning in `core/src/spawn.rs` and the platform
wrappers to use `NetworkSandboxPolicy` when deciding whether to set
`CODEX_SANDBOX_NETWORK_DISABLED`
- kept additional-permissions handling and legacy `ExternalSandbox`
compatibility projections aligned with the split policies, including
explicit user-shell execution and Windows restricted-token routing
- updated callers across `core`, `app-server`, and `linux-sandbox` to
pass the split policies explicitly

## Verification

- added regression coverage in `core/tests/suite/user_shell_cmd.rs` to
verify `RunUserShellCommand` does not inherit
`CODEX_SANDBOX_NETWORK_DISABLED` from the active turn
- added coverage in `core/src/exec.rs` for Windows restricted-token
sandbox selection when the legacy projection is `ExternalSandbox`
- updated Linux sandbox coverage in
`linux-sandbox/tests/suite/landlock.rs` to exercise the split-policy
exec path
- verified the current PR state with `just clippy`




---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/13439).
* #13453
* #13452
* #13451
* #13449
* #13448
* #13445
* #13440
* __->__ #13439

---------

Co-authored-by: viyatb-oai <viyatb@openai.com>
2026-03-07 02:30:21 +00:00
..
src fix(linux-sandbox): always unshare bwrap userns (#13624) 2026-03-05 21:57:40 +00:00
tests sandboxing: plumb split sandbox policies through runtime (#13439) 2026-03-07 02:30:21 +00:00
BUILD.bazel build(linux-sandbox): always compile vendored bubblewrap on Linux; remove CODEX_BWRAP_ENABLE_FFI (#11498) 2026-02-11 21:30:41 -08:00
build.rs build(linux-sandbox): always compile vendored bubblewrap on Linux; remove CODEX_BWRAP_ENABLE_FFI (#11498) 2026-02-11 21:30:41 -08:00
Cargo.toml feat(linux-sandbox): implement proxy-only egress via TCP-UDS-TCP bridge (#11293) 2026-02-21 18:16:34 +00:00
config.h build(linux-sandbox): always compile vendored bubblewrap on Linux; remove CODEX_BWRAP_ENABLE_FFI (#11498) 2026-02-11 21:30:41 -08:00
README.md fix(linux-sandbox): always unshare bwrap userns (#13624) 2026-03-05 21:57:40 +00:00

codex-linux-sandbox

This crate is responsible for producing:

  • a codex-linux-sandbox standalone executable for Linux that is bundled with the Node.js version of the Codex CLI
  • a lib crate that exposes the business logic of the executable as run_main() so that
    • the codex-exec CLI can check if its arg0 is codex-linux-sandbox and, if so, execute as if it were codex-linux-sandbox
    • this should also be true of the codex multitool CLI

On Linux, the bubblewrap pipeline uses the vendored bubblewrap path compiled into this binary.

Current Behavior

  • Legacy Landlock + mount protections remain available as the legacy pipeline.
  • The bubblewrap pipeline is standardized on the vendored path.
  • During rollout, the bubblewrap pipeline is gated by the temporary feature flag use_linux_sandbox_bwrap (CLI -c alias for features.use_linux_sandbox_bwrap; legacy remains default when off).
  • When enabled, the bubblewrap pipeline applies PR_SET_NO_NEW_PRIVS and a seccomp network filter in-process.
  • When enabled, the filesystem is read-only by default via --ro-bind / /.
  • When enabled, writable roots are layered with --bind <root> <root>.
  • When enabled, protected subpaths under writable roots (for example .git, resolved gitdir:, and .codex) are re-applied as read-only via --ro-bind.
  • When enabled, symlink-in-path and non-existent protected paths inside writable roots are blocked by mounting /dev/null on the symlink or first missing component.
  • When enabled, the helper explicitly isolates the user namespace via --unshare-user and the PID namespace via --unshare-pid.
  • When enabled and network is restricted without proxy routing, the helper also isolates the network namespace via --unshare-net.
  • In managed proxy mode, the helper uses --unshare-net plus an internal TCP->UDS->TCP routing bridge so tool traffic reaches only configured proxy endpoints.
  • In managed proxy mode, after the bridge is live, seccomp blocks new AF_UNIX/socketpair creation for the user command.
  • When enabled, it mounts a fresh /proc via --proc /proc by default, but you can skip this in restrictive container environments with --no-proc.

Notes

  • The CLI surface still uses legacy names like codex debug landlock.