mirror of
https://github.com/openai/codex.git
synced 2026-05-15 00:32:51 +00:00
**Summary** - Add `codex-bwrap`, a standalone `bwrap` binary built from the existing vendored bubblewrap sources. - Remove the linked vendored bwrap path from `codex-linux-sandbox`; runtime now prefers system `bwrap` and falls back to bundled `codex-resources/bwrap`. - Add bundled SHA-256 verification with missing/all-zero digest as the dev-mode skip value, then exec the verified file through `/proc/self/fd`. - Keep `launcher.rs` focused on choosing and dispatching the preferred launcher. Bundled lookup, digest verification, and bundled exec now live in `linux-sandbox/src/bundled_bwrap.rs`; Bazel runfiles lookup lives in `linux-sandbox/src/bazel_bwrap.rs`; shared argv/fd exec helpers live in `linux-sandbox/src/exec_util.rs`. - Teach Bazel tests to surface the Bazel-built `//codex-rs/bwrap:bwrap` through `CARGO_BIN_EXE_bwrap`; `codex-linux-sandbox` only honors that fallback in debug Bazel runfiles environments so release/user runtime lookup stays tied to `codex-resources/bwrap`. - Allow `codex-exec-server` filesystem helpers to preserve just the Bazel bwrap/runfiles variables they need in debug Bazel builds, since those helpers intentionally rebuild a small environment before spawning `codex-linux-sandbox`. - Verify the Bazel bwrap target in Linux release CI with a build-only check. Running `bwrap --version` is too strong for GitHub runners because bubblewrap still attempts namespace setup there. **Verification** - Latest update: `cargo test -p codex-linux-sandbox` - Latest update: `just fix -p codex-linux-sandbox` - `cargo check --target x86_64-unknown-linux-gnu -p codex-linux-sandbox` could not run locally because this macOS machine does not have `x86_64-linux-gnu-gcc`; GitHub Linux Bazel CI is expected to cover the Linux-only modules. - Earlier in this PR: `cargo test -p codex-bwrap` - Earlier in this PR: `cargo test -p codex-exec-server` - Earlier in this PR: `cargo check --release -p codex-exec-server` - Earlier in this PR: `just fix -p codex-linux-sandbox -p codex-exec-server` - Earlier in this PR: `bazel test --nobuild //codex-rs/linux-sandbox:linux-sandbox-all-test //codex-rs/core:core-all-test //codex-rs/exec-server:exec-server-file_system-test //codex-rs/app-server:app-server-all-test` (analysis completed; Bazel then refuses to run tests under `--nobuild`) - Earlier in this PR: `bazel build --nobuild //codex-rs/bwrap:bwrap` - Prior to this update: `just bazel-lock-update`, `just bazel-lock-check`, and YAML parse check for `.github/workflows/bazel.yml` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/21255). * #21257 * #21256 * __->__ #21255
98 lines
5.1 KiB
Markdown
98 lines
5.1 KiB
Markdown
# 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, Codex prefers the first `bwrap` found on `PATH`
|
|
outside the current working directory whenever it is available. If `bwrap` is
|
|
present but too old to support
|
|
`--argv0`, the helper keeps using system bubblewrap and switches to a
|
|
no-`--argv0` compatibility path for the inner re-exec. If `bwrap` is missing,
|
|
the helper falls back to the bundled `codex-resources/bwrap` binary shipped
|
|
with Codex.
|
|
Codex also surfaces a startup warning when `bwrap` is missing so users know it
|
|
is falling back to the bundled helper. Codex surfaces the same startup warning
|
|
path when bubblewrap cannot create user namespaces. WSL2 follows the normal
|
|
Linux bubblewrap path. WSL1 is not supported for bubblewrap sandboxing because
|
|
it cannot create the required user namespaces, so Codex rejects sandboxed shell
|
|
commands that would enter the bubblewrap path.
|
|
|
|
**Current Behavior**
|
|
- Legacy `SandboxPolicy` / `sandbox_mode` configs remain supported.
|
|
- Bubblewrap is the default filesystem sandbox.
|
|
- If `bwrap` is present on `PATH` outside the current working directory, the
|
|
helper uses it.
|
|
- If `bwrap` is present but too old to support `--argv0`, the helper uses a
|
|
no-`--argv0` compatibility path for the inner re-exec.
|
|
- If `bwrap` is missing, the helper falls back to the bundled
|
|
`codex-resources/bwrap` path.
|
|
- If `bwrap` is missing, Codex also surfaces a startup warning instead of
|
|
printing directly from the sandbox helper.
|
|
- If bubblewrap cannot create user namespaces, Codex surfaces a startup warning
|
|
instead of waiting for a runtime sandbox failure.
|
|
- WSL2 uses the normal Linux bubblewrap path.
|
|
- WSL1 is not supported for bubblewrap sandboxing; Codex rejects sandboxed
|
|
shell commands that would require the bubblewrap path before invoking `bwrap`.
|
|
- Legacy Landlock + mount protections remain available as an explicit legacy
|
|
fallback path.
|
|
- Set `features.use_legacy_landlock = true` (or CLI `-c use_legacy_landlock=true`)
|
|
to force the legacy Landlock fallback.
|
|
- The legacy Landlock fallback is used only when the split filesystem policy is
|
|
sandbox-equivalent to the legacy model after `cwd` resolution.
|
|
- Split-only filesystem policies that do not round-trip through the legacy
|
|
`SandboxPolicy` model stay on bubblewrap so nested read-only or denied
|
|
carveouts are preserved.
|
|
- When bubblewrap is active, the helper applies `PR_SET_NO_NEW_PRIVS` and a
|
|
seccomp network filter in-process.
|
|
- When bubblewrap is active, the filesystem is read-only by default via `--ro-bind / /`.
|
|
- When bubblewrap is active, writable roots are layered with `--bind <root> <root>`.
|
|
- When bubblewrap is active, protected subpaths under writable roots (for
|
|
example `.git`,
|
|
resolved `gitdir:`, and `.codex`) are re-applied as read-only via `--ro-bind`.
|
|
- When bubblewrap is active, overlapping split-policy
|
|
entries are applied in path-specificity order so narrower writable children
|
|
can reopen broader read-only or denied parents while narrower denied subpaths
|
|
still win. For example, `/repo = write`, `/repo/a = none`, `/repo/a/b = write`
|
|
keeps `/repo` writable, denies `/repo/a`, and reopens `/repo/a/b` as
|
|
writable again.
|
|
- When bubblewrap is active, unreadable glob entries are expanded before
|
|
launching the sandbox and matching files are masked in bubblewrap:
|
|
|
|
```text
|
|
Prefer: rg --files --hidden --no-ignore --glob <pattern> -- <search-root>
|
|
Fallback: internal globset walker when rg is not installed
|
|
Failure: any other rg failure aborts sandbox construction
|
|
```
|
|
|
|
Users can cap the scan depth per permissions profile:
|
|
|
|
```toml
|
|
[permissions.workspace.filesystem]
|
|
glob_scan_max_depth = 2
|
|
|
|
[permissions.workspace.filesystem.":project_roots"]
|
|
"**/*.env" = "none"
|
|
```
|
|
|
|
- When bubblewrap is active, 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 bubblewrap is active, the helper explicitly isolates the user namespace via
|
|
`--unshare-user` and the PID namespace via `--unshare-pid`.
|
|
- When bubblewrap is active 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 bubblewrap is active, 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`.
|