Files
codex/codex-rs/linux-sandbox
Michael Bolin ee4c217a44 Make sandbox read access configurable with ReadOnlyAccess
## What

This change introduces a new `ReadOnlyAccess` model and threads it through
sandbox policy consumers so read access is explicit instead of implicit.

- Added `ReadOnlyAccess` to protocol:
  - `Restricted { include_platform_defaults, readable_roots }`
  - `FullAccess`
- Changed `SandboxPolicy` shape:
  - `ReadOnly` is now `ReadOnly { access: ReadOnlyAccess }`
  - `WorkspaceWrite` now carries `read_only_access: ReadOnlyAccess`
- Kept existing behavior for now by defaulting to `ReadOnlyAccess::FullAccess`
  in constructors and current config/app-server mappings.
- Added helper methods to compute effective readable roots (including optional
  platform defaults + cwd) and to detect full read access.
- Updated seatbelt policy generation to honor restricted read roots by emitting
  scoped `(allow file-read* ...)` entries when full read access is not granted.
- Updated Linux backends (`bwrap`, legacy landlock path) to fail closed with an
  explicit `UnsupportedOperation` when restricted read access is requested but
  not yet implemented there.
- Updated Windows sandbox backends (standard, elevated, and runner paths) to
  fail closed in the same way for restricted read access.
- Updated all call sites/tests/pattern matches for the new structured variants
  and regenerated app-server protocol schema/types.

## Why

The previous `SandboxPolicy::ReadOnly` implied full-disk read access and left
no way to express a narrower read surface.

This refactor establishes the policy model needed to support user-configurable
read restrictions in a follow-up without changing current runtime behavior.

It also ensures we do not silently ignore future restricted-read policies on
platform backends that do not support them yet. Failing closed keeps sandbox
semantics predictable and avoids accidental over-permission.

## Compatibility and rollout notes

- Existing behavior is preserved by default (`FullAccess`).
- Existing config/app-server flows continue to serialize/deserialize cleanly.
- New schema artifacts are included to keep generated protocol outputs in sync.

## Validation

- `just fmt`
- `just fix -p codex-protocol -p codex-core -p codex-linux-sandbox -p codex-windows-sandbox -p codex-app-server-protocol`
- `cargo check -p codex-windows-sandbox`
- Targeted crate/test runs were executed during development for protocol/core/
  sandbox-related crates.
2026-02-10 19:56:37 -08: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 isolates 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.
  • 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.