24 Commits

  • runtime: use install context for bundled bwrap (#23634)
    ## Summary
    
    The Linux sandbox should find bundled `bwrap` through the same
    package-layout abstraction as the rest of the runtime, instead of
    maintaining a separate standalone-specific lookup path.
    
    This adds an `InstallContext` helper for bundled resources and updates
    `codex-linux-sandbox` to ask the current install context for
    `codex-resources/bwrap` before falling back to the old
    executable-relative probes. The tests cover npm-style, standalone, and
    canonical package layouts so `bwrap` lookup follows the package
    structure introduced earlier in the stack.
    
    ## Test plan
    
    - `cargo test -p codex-install-context`
    - `cargo test -p codex-linux-sandbox --lib`
    - `just fix -p codex-install-context -p codex-linux-sandbox`
    - `just bazel-lock-check`
    
    
    
    
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/23634).
    * #23638
    * #23637
    * #23636
    * #23635
    * __->__ #23634
  • Disable empty Cargo test targets (#21584)
    ## Summary
    
    `cargo test` has entails both running standard Rust tests and doctests.
    It turns out that the doctest discovery is fairly slow, and it's a cost
    you pay even for crates that don't include any doctests.
    
    This PR disables doctests with `doctest = false` for crates that lack
    any doctests.
    
    For the collection of crates below, this speeds up test execution by
    >4x.
    
    E.g., before this PR:
    
    ```
    Benchmark 1: cargo test     -p codex-utils-absolute-path     -p codex-utils-cache     -p codex-utils-cli     -p codex-utils-home-dir     -p codex-utils-output-truncation     -p codex-utils-path     -p codex-utils-string     -p codex-utils-template     -p codex-utils-elapsed     -p codex-utils-json-to-toml
      Time (mean ± σ):      1.849 s ±  4.455 s    [User: 0.752 s, System: 1.367 s]
      Range (min … max):    0.418 s … 14.529 s    10 runs
    ```
    
    And after:
    
    ```
    Benchmark 1: cargo test     -p codex-utils-absolute-path     -p codex-utils-cache     -p codex-utils-cli     -p codex-utils-home-dir     -p codex-utils-output-truncation     -p codex-utils-path     -p codex-utils-string     -p codex-utils-template     -p codex-utils-elapsed     -p codex-utils-json-to-toml
      Time (mean ± σ):     428.6 ms ±   6.9 ms    [User: 187.7 ms, System: 219.7 ms]
      Range (min … max):   418.0 ms … 436.8 ms    10 runs
    ```
    
    For a single crate, with >2x speedup, before:
    
    ```
    Benchmark 1: cargo test -p codex-utils-string
      Time (mean ± σ):     491.1 ms ±   9.0 ms    [User: 229.8 ms, System: 234.9 ms]
      Range (min … max):   480.9 ms … 512.0 ms    10 runs
    ```
    
    And after:
    
    ```
    Benchmark 1: cargo test -p codex-utils-string
      Time (mean ± σ):     213.9 ms ±   4.3 ms    [User: 112.8 ms, System: 84.0 ms]
      Range (min … max):   206.8 ms … 221.0 ms    13 runs
    ```
    
    Co-authored-by: Codex <noreply@openai.com>
  • linux-sandbox: use standalone bundled bwrap (#21255)
    **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
  • fix(network-proxy): harden linux proxy bridge helpers (#20001)
    ## Why
    The Linux managed-proxy bridge helpers are long-lived child processes in
    the sandbox networking path. Before this change they stayed dumpable and
    the network seccomp profile did not block cross-process memory syscalls,
    so another same-user process could potentially inspect or modify bridge
    memory instead of interacting only through the intended proxy interface.
    
    ## What changed
    - reuse the shared `codex-process-hardening` helper to mark bridge
    helper children non-dumpable before they begin serving
    - deny `process_vm_readv` and `process_vm_writev` in the existing
    network seccomp filter
    
    ## Security impact
    Bridge helpers are less exposed to same-user cross-process inspection or
    memory writes, which reduces the chance that sandboxed code can
    interfere with proxy support processes outside the intended IPC path.
    
    ## Verification
    - `cargo test -p codex-process-hardening`
    - `cargo test -p codex-linux-sandbox`
    - attempted `cargo check -p codex-linux-sandbox --target
    x86_64-unknown-linux-gnu`; blocked on missing `x86_64-linux-gnu-gcc` on
    this macOS host
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • [codex] Move config loading into codex-config (#19487)
    ## Why
    
    Config loading had become split across crates: `codex-config` owned the
    config types and merge logic, while `codex-core` still owned the loader
    that assembled the layer stack. This change consolidates that
    responsibility in `codex-config`, so the crate that defines config
    behavior also owns how configs are discovered and loaded.
    
    To make that move possible without reintroducing the old dependency
    cycle, the shell-environment policy types and helpers that
    `codex-exec-server` needs now live in `codex-protocol` instead of
    flowing through `codex-config`.
    
    This also makes the migrated loader tests more deterministic on machines
    that already have managed or system Codex config installed by letting
    tests override the system config and requirements paths instead of
    reading the host's `/etc/codex`.
    
    ## What Changed
    
    - moved the config loader implementation from `codex-core` into
    `codex-config::loader` and deleted the old `core::config_loader` module
    instead of leaving a compatibility shim
    - moved shell-environment policy types and helpers into
    `codex-protocol`, then updated `codex-exec-server` and other downstream
    crates to import them from their new home
    - updated downstream callers to use loader/config APIs from
    `codex-config`
    - added test-only loader overrides for system config and requirements
    paths so loader-focused tests do not depend on host-managed config state
    - cleaned up now-unused dependency entries and platform-specific cfgs
    that were surfaced by post-push CI
    
    ## Testing
    
    - `cargo test -p codex-config`
    - `cargo test -p codex-core config_loader_tests::`
    - `cargo test -p codex-protocol -p codex-exec-server -p
    codex-cloud-requirements -p codex-rmcp-client --lib`
    - `cargo test --lib -p codex-app-server-client -p codex-exec`
    - `cargo test --no-run --lib -p codex-app-server`
    - `cargo test -p codex-linux-sandbox --lib`
    - `cargo shear`
    - `just bazel-lock-check`
    
    ## Notes
    
    - I did not chase unrelated full-suite failures outside the migrated
    loader surface.
    - `cargo test -p codex-core --lib` still hits unrelated proxy-sensitive
    failures on this machine, and Windows CI still shows unrelated
    long-running/timeouting test noise outside the loader migration itself.
  • feat(sandbox): add glob deny-read platform enforcement (#18096)
    ## Summary
    - adds macOS Seatbelt deny rules for unreadable glob patterns
    - expands unreadable glob matches on Linux and masks them in bwrap,
    including canonical symlink targets
    - keeps Linux glob expansion robust when `rg` is unavailable in minimal
    or Bazel test environments
    - adds sandbox integration coverage that runs `shell` and `exec_command`
    with a `**/*.env = none` policy and verifies the secret contents do not
    reach the model
    
    ## Linux glob expansion
    
    ```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
    ```
    
    ```
    [permissions.workspace.filesystem]
    glob_scan_max_depth = 2
    
    [permissions.workspace.filesystem.":project_roots"]
    "**/*.env" = "none"
    ```
    
    
    This keeps the common path fast without making sandbox construction
    depend on an ambient `rg` binary. If `rg` is present but fails for
    another reason, the sandbox setup fails closed instead of silently
    omitting deny-read masks.
    
    ## Platform support
    - macOS: subprocess sandbox enforcement is handled by Seatbelt regex
    deny rules
    - Linux: subprocess sandbox enforcement is handled by expanding existing
    glob matches and masking them in bwrap
    - Windows: policy/config/direct-tool glob support is already on `main`
    from #15979; Windows subprocess sandbox paths continue to fail closed
    when unreadable split filesystem carveouts require runtime enforcement,
    rather than silently running unsandboxed
    
    ## Stack
    1. #15979 - merged: cross-platform glob deny-read
    policy/config/direct-tool support for macOS, Linux, and Windows
    2. This PR - macOS/Linux subprocess sandbox enforcement plus Windows
    fail-closed clarification
    3. #17740 - managed deny-read requirements
    
    ## Verification
    - Added integration coverage for `shell` and `exec_command` glob
    deny-read enforcement
    - `cargo check -p codex-sandboxing -p codex-linux-sandbox --tests`
    - `cargo check -p codex-core --test all`
    - `cargo clippy -p codex-linux-sandbox -p codex-sandboxing --tests`
    - `just bazel-lock-check`
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • Refactor config types into a separate crate (#16962)
    Move config types into a separate crate because their macros expand into
    a lot of new code.
  • [codex] Remove codex-core config type shim (#16529)
    ## Why
    
    This finishes the config-type move out of `codex-core` by removing the
    temporary compatibility shim in `codex_core::config::types`. Callers now
    depend on `codex-config` directly, which keeps these config model types
    owned by the config crate instead of re-expanding `codex-core` as a
    transitive API surface.
    
    ## What Changed
    
    - Removed the `codex-rs/core/src/config/types.rs` re-export shim and the
    `core::config::ApprovalsReviewer` re-export.
    - Updated `codex-core`, `codex-cli`, `codex-tui`, `codex-app-server`,
    `codex-mcp-server`, and `codex-linux-sandbox` call sites to import
    `codex_config::types` directly.
    - Added explicit `codex-config` dependencies to downstream crates that
    previously relied on the `codex-core` re-export.
    - Regenerated `codex-rs/core/config.schema.json` after updating the
    config docs path reference.
  • fix: fix old system bubblewrap compatibility without falling back to vendored bwrap (#15693)
    Fixes #15283.
    
    ## Summary
    Older system bubblewrap builds reject `--argv0`, which makes our Linux
    sandbox fail before the helper can re-exec. This PR keeps using system
    `/usr/bin/bwrap` whenever it exists and only falls back to vendored
    bwrap when the system binary is missing. That matters on stricter
    AppArmor hosts, where the distro bwrap package also provides the policy
    setup needed for user namespaces.
    
    For old system bwrap, we avoid `--argv0` instead of switching binaries:
    - pass the sandbox helper a full-path `argv0`,
    - keep the existing `current_exe() + --argv0` path when the selected
    launcher supports it,
    - otherwise omit `--argv0` and re-exec through the helper's own
    `argv[0]` path, whose basename still dispatches as
    `codex-linux-sandbox`.
    
    Also updates the launcher/warning tests and docs so they match the new
    behavior: present-but-old system bwrap uses the compatibility path, and
    only absent system bwrap falls back to vendored.
    
    ### Validation
    
    1. Install Ubuntu 20.04 in a VM
    2. Compile codex and run without bubblewrap installed - see a warning
    about falling back to the vendored bwrap
    3. Install bwrap and verify version is 0.4.0 without `argv0` support
    4. run codex and use apply_patch tool without errors
    
    <img width="802" height="631" alt="Screenshot 2026-03-25 at 11 48 36 PM"
    src="https://github.com/user-attachments/assets/77248a29-aa38-4d7c-9833-496ec6a458b8"
    />
    <img width="807" height="634" alt="Screenshot 2026-03-25 at 11 47 32 PM"
    src="https://github.com/user-attachments/assets/5af8b850-a466-489b-95a6-455b76b5050f"
    />
    <img width="812" height="635" alt="Screenshot 2026-03-25 at 11 45 45 PM"
    src="https://github.com/user-attachments/assets/438074f0-8435-4274-a667-332efdd5cb57"
    />
    <img width="801" height="623" alt="Screenshot 2026-03-25 at 11 43 56 PM"
    src="https://github.com/user-attachments/assets/0dc8d3f5-e8cf-4218-b4b4-a4f7d9bf02e3"
    />
    
    ---------
    
    Co-authored-by: Michael Bolin <mbolin@openai.com>
  • feat(linux-sandbox): implement proxy-only egress via TCP-UDS-TCP bridge (#11293)
    ## Summary
    - Implement Linux proxy-only routing in `codex-rs/linux-sandbox` with a
    two-stage bridge: host namespace `loopback TCP proxy endpoint -> UDS`,
    then bwrap netns `loopback TCP listener -> host UDS`.
    - Add hidden `--proxy-route-spec` plumbing for outer-to-inner stage
    handoff.
    - Fail closed in proxy mode when no valid loopback proxy endpoints can
    be routed.
    - Introduce explicit network seccomp modes: `Restricted` (legacy
    restricted networking) and `ProxyRouted` (allow INET/INET6 for routed
    proxy access, deny `AF_UNIX` and `socketpair`).
    - Enforce that proxy bridge/routing is bwrap-only by validating
    `--apply-seccomp-then-exec` requires `--use-bwrap-sandbox`.
    - Keep landlock-only flows unchanged (no proxy bridge behavior outside
    bwrap).
    
    ---------
    
    Co-authored-by: Codex <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
  • chore: remove codex-core public protocol/shell re-exports (#12432)
    ## Why
    
    `codex-rs/core/src/lib.rs` re-exported a broad set of types and modules
    from `codex-protocol` and `codex-shell-command`. That made it easy for
    workspace crates to import those APIs through `codex-core`, which in
    turn hides dependency edges and makes it harder to reduce compile-time
    coupling over time.
    
    This change removes those public re-exports so call sites must import
    from the source crates directly. Even when a crate still depends on
    `codex-core` today, this makes dependency boundaries explicit and
    unblocks future work to drop `codex-core` dependencies where possible.
    
    ## What Changed
    
    - Removed public re-exports from `codex-rs/core/src/lib.rs` for:
    - `codex_protocol::protocol` and related protocol/model types (including
    `InitialHistory`)
      - `codex_protocol::config_types` (`protocol_config_types`)
    - `codex_shell_command::{bash, is_dangerous_command, is_safe_command,
    parse_command, powershell}`
    - Migrated workspace Rust call sites to import directly from:
      - `codex_protocol::protocol`
      - `codex_protocol::config_types`
      - `codex_protocol::models`
      - `codex_shell_command`
    - Added explicit `Cargo.toml` dependencies (`codex-protocol` /
    `codex-shell-command`) in crates that now import those crates directly.
    - Kept `codex-core` internal modules compiling by using `pub(crate)`
    aliases in `core/src/lib.rs` (internal-only, not part of the public
    API).
    - Updated the two utility crates that can already drop a `codex-core`
    dependency edge entirely:
      - `codex-utils-approval-presets`
      - `codex-utils-cli`
    
    ## Verification
    
    - `cargo test -p codex-utils-approval-presets`
    - `cargo test -p codex-utils-cli`
    - `cargo check --workspace --all-targets`
    - `just clippy`
  • feat(linux-sandbox): add bwrap support (#9938)
    ## Summary
    This PR introduces a gated Bubblewrap (bwrap) Linux sandbox path. The
    curent Linux sandbox path relies on in-process restrictions (including
    Landlock). Bubblewrap gives us a more uniform filesystem isolation
    model, especially explicit writable roots with the option to make some
    directories read-only and granular network controls.
    
    This is behind a feature flag so we can validate behavior safely before
    making it the default.
    
    - Added temporary rollout flag:
      - `features.use_linux_sandbox_bwrap`
    - Preserved existing default path when the flag is off.
    - In Bubblewrap mode:
    - Added internal retry without /proc when /proc mount is not permitted
    by the host/container.
  • feat(linux-sandbox): vendor bubblewrap and wire it with FFI (#10413)
    ## Summary
    
    Vendor Bubblewrap into the repo and add minimal build plumbing in
    `codex-linux-sandbox` to compile/link it.
    
    ## Why
    
    We want to move Linux sandboxing toward Bubblewrap, but in a safe
    two-step rollout:
    1) vendoring/build setup (this PR),  
    2) runtime integration (follow-up PR).
    
    ## Included
    
    - Add `codex-rs/vendor/bubblewrap` sources.
    - Add build-time FFI path in `codex-rs/linux-sandbox`.
    - Update `build.rs` rerun tracking for vendored files.
    - Small vendored compile warning fix (`sockaddr_nl` full init).
    
    follow up in https://github.com/openai/codex/pull/9938
  • fix: fallback to Landlock-only when user namespaces unavailable and set PR_SET_NO_NEW_PRIVS early (#9250)
    fixes https://github.com/openai/codex/issues/9236
    
    ### Motivation
    - Prevent sandbox setup from failing when unprivileged user namespaces
    are denied so Landlock-only protections can still be applied.
    - Ensure `PR_SET_NO_NEW_PRIVS` is set before installing seccomp and
    Landlock restrictions to avoid kernel `EPERM`/`LandlockRestrict`
    ordering issues.
    
    ### Description
    - Add `is_permission_denied` helper that detects `EPERM` /
    `PermissionDenied` from `CodexErr` to drive fallback logic.
    - In `apply_read_only_mounts` skip read-only bind-mount setup and return
    `Ok(())` when `unshare_user_and_mount_namespaces()` fails with
    permission-denied so Landlock rules can still be installed.
    - Add `set_no_new_privs()` and call it from
    `apply_sandbox_policy_to_current_thread` before installing seccomp
    filters and Landlock rules when disk or network access is restricted.
  • fix: introduce AbsolutePathBuf as part of sandbox config (#7856)
    Changes the `writable_roots` field of the `WorkspaceWrite` variant of
    the `SandboxPolicy` enum from `Vec<PathBuf>` to `Vec<AbsolutePathBuf>`.
    This is helpful because now callers can be sure the value is an absolute
    path rather than a relative one. (Though when using an absolute path in
    a Seatbelt config policy, we still have to _canonicalize_ it first.)
    
    Because `writable_roots` can be read from a config file, it is important
    that we are able to resolve relative paths properly using the parent
    folder of the config file as the base path.
  • chore: add cargo-deny configuration (#7119)
    - add GitHub workflow running cargo-deny on push/PR
    - document cargo-deny allowlist with workspace-dep notes and advisory
    ignores
    - align workspace crates to inherit version/edition/license for
    consistent checks
  • chore: unify cargo versions (#4044)
    Unify cargo versions at root
  • feat: Run cargo shear during CI (#3338)
    Run cargo shear as part of the CI to ensure no unused dependencies
  • chore(deps): bump libc from 0.2.174 to 0.2.175 in /codex-rs (#2406)
    Bumps [libc](https://github.com/rust-lang/libc) from 0.2.174 to 0.2.175.
    <details>
    <summary>Release notes</summary>
    <p><em>Sourced from <a
    href="https://github.com/rust-lang/libc/releases">libc's
    releases</a>.</em></p>
    <blockquote>
    <h2>0.2.175</h2>
    <h3>Added</h3>
    <ul>
    <li>AIX: Add <code>getpeereid</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4524">#4524</a>)</li>
    <li>AIX: Add <code>struct ld_info</code> and friends (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4578">#4578</a>)</li>
    <li>AIX: Retore <code>struct winsize</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4577">#4577</a>)</li>
    <li>Android: Add UDP socket option constants (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4619">#4619</a>)</li>
    <li>Android: Add <code>CLONE_CLEAR_SIGHAND</code> and
    <code>CLONE_INTO_CGROUP</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4502">#4502</a>)</li>
    <li>Android: Add more <code>prctl</code> constants (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4531">#4531</a>)</li>
    <li>FreeBSD Add further TCP stack-related constants (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4196">#4196</a>)</li>
    <li>FreeBSD x86-64: Add <code>mcontext_t.mc_tlsbase </code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4503">#4503</a>)</li>
    <li>FreeBSD15: Add <code>kinfo_proc.ki_uerrmsg</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4552">#4552</a>)</li>
    <li>FreeBSD: Add <code>in_conninfo</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4482">#4482</a>)</li>
    <li>FreeBSD: Add <code>xinpgen</code> and related types (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4482">#4482</a>)</li>
    <li>FreeBSD: Add <code>xktls_session</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4482">#4482</a>)</li>
    <li>Haiku: Add functionality from <code>libbsd</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4221">#4221</a>)</li>
    <li>Linux: Add <code>SECBIT_*</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4480">#4480</a>)</li>
    <li>NetBSD, OpenBSD: Export <code>ioctl</code> request generator macros
    (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4460">#4460</a>)</li>
    <li>NetBSD: Add <code>ptsname_r</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4608">#4608</a>)</li>
    <li>RISCV32: Add time-related syscalls (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4612">#4612</a>)</li>
    <li>Solarish: Add <code>strftime*</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4453">#4453</a>)</li>
    <li>linux: Add <code>EXEC_RESTRICT_*</code> and <code>EXEC_DENY_*</code>
    (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4545">#4545</a>)</li>
    </ul>
    <h3>Changed</h3>
    <ul>
    <li>AIX: Add <code>const</code> to signatures to be consistent with
    other platforms (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4563">#4563</a>)</li>
    </ul>
    <h3>Fixed</h3>
    <ul>
    <li>AIX: Fix the type of <code>struct statvfs.f_fsid</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4576">#4576</a>)</li>
    <li>AIX: Fix the type of constants for the <code>ioctl</code>
    <code>request</code> argument (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4582">#4582</a>)</li>
    <li>AIX: Fix the types of <code>stat{,64}.st_*tim</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4597">#4597</a>)</li>
    <li>AIX: Use unique <code>errno</code> values (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4507">#4507</a>)</li>
    <li>Build: Fix an incorrect <code>target_os</code> -&gt;
    <code>target_arch</code> check (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4550">#4550</a>)</li>
    <li>FreeBSD: Fix the type of <code>xktls_session_onedir.ifnet</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4552">#4552</a>)</li>
    <li>Mips64 musl: Fix the type of <code>nlink_t</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4509">#4509</a>)</li>
    <li>Mips64 musl: Use a special MIPS definition of <code>stack_t</code>
    (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4528">#4528</a>)</li>
    <li>Mips64: Fix <code>SI_TIMER</code>, <code>SI_MESGQ</code> and
    <code>SI_ASYNCIO</code> definitions (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4529">#4529</a>)</li>
    <li>Musl Mips64: Swap the order of <code>si_errno</code> and
    <code>si_code</code> in <code>siginfo_t</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4530">#4530</a>)</li>
    <li>Musl Mips64: Use a special MIPS definition of <code>statfs</code>
    (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4527">#4527</a>)</li>
    <li>Musl: Fix the definition of <code>fanotify_event_metadata</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4510">#4510</a>)</li>
    <li>NetBSD: Correct <code>enum fae_action</code> to be
    <code>#[repr(C)]</code> (<a
    href="https://github.com/rust-lang/libc/commit/60a8cfd564f83164d45b9533ff7a0d7371878f2a">#60a8cfd5</a>)</li>
    <li>PSP: Correct <code>char</code> -&gt; <code>c_char</code> (<a
    href="https://github.com/rust-lang/libc/commit/eaab4fc3f05dc646a953d4fd5ba46dfa1f8bd6f6">eaab4fc3</a>)</li>
    <li>PowerPC musl: Fix <code>termios</code> definitions (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4518">#4518</a>)</li>
    <li>PowerPC musl: Fix the definition of <code>EDEADLK</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4517">#4517</a>)</li>
    <li>PowerPC musl: Fix the definition of <code>NCCS</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4513">#4513</a>)</li>
    <li>PowerPC musl: Fix the definitions of <code>MAP_LOCKED</code> and
    <code>MAP_NORESERVE</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4516">#4516</a>)</li>
    <li>PowerPC64 musl: Fix the definition of <code>shmid_ds</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4519">#4519</a>)</li>
    </ul>
    <h3>Deprecated</h3>
    <!-- raw HTML omitted -->
    </blockquote>
    <p>... (truncated)</p>
    </details>
    <details>
    <summary>Changelog</summary>
    <p><em>Sourced from <a
    href="https://github.com/rust-lang/libc/blob/0.2.175/CHANGELOG.md">libc's
    changelog</a>.</em></p>
    <blockquote>
    <h2><a
    href="https://github.com/rust-lang/libc/compare/0.2.174...0.2.175">0.2.175</a>
    - 2025-08-10</h2>
    <h3>Added</h3>
    <ul>
    <li>AIX: Add <code>getpeereid</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4524">#4524</a>)</li>
    <li>AIX: Add <code>struct ld_info</code> and friends (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4578">#4578</a>)</li>
    <li>AIX: Retore <code>struct winsize</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4577">#4577</a>)</li>
    <li>Android: Add UDP socket option constants (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4619">#4619</a>)</li>
    <li>Android: Add <code>CLONE_CLEAR_SIGHAND</code> and
    <code>CLONE_INTO_CGROUP</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4502">#4502</a>)</li>
    <li>Android: Add more <code>prctl</code> constants (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4531">#4531</a>)</li>
    <li>FreeBSD Add further TCP stack-related constants (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4196">#4196</a>)</li>
    <li>FreeBSD x86-64: Add <code>mcontext_t.mc_tlsbase </code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4503">#4503</a>)</li>
    <li>FreeBSD15: Add <code>kinfo_proc.ki_uerrmsg</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4552">#4552</a>)</li>
    <li>FreeBSD: Add <code>in_conninfo</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4482">#4482</a>)</li>
    <li>FreeBSD: Add <code>xinpgen</code> and related types (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4482">#4482</a>)</li>
    <li>FreeBSD: Add <code>xktls_session</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4482">#4482</a>)</li>
    <li>Haiku: Add functionality from <code>libbsd</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4221">#4221</a>)</li>
    <li>Linux: Add <code>SECBIT_*</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4480">#4480</a>)</li>
    <li>NetBSD, OpenBSD: Export <code>ioctl</code> request generator macros
    (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4460">#4460</a>)</li>
    <li>NetBSD: Add <code>ptsname_r</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4608">#4608</a>)</li>
    <li>RISCV32: Add time-related syscalls (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4612">#4612</a>)</li>
    <li>Solarish: Add <code>strftime*</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4453">#4453</a>)</li>
    <li>linux: Add <code>EXEC_RESTRICT_*</code> and <code>EXEC_DENY_*</code>
    (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4545">#4545</a>)</li>
    </ul>
    <h3>Changed</h3>
    <ul>
    <li>AIX: Add <code>const</code> to signatures to be consistent with
    other platforms (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4563">#4563</a>)</li>
    </ul>
    <h3>Fixed</h3>
    <ul>
    <li>AIX: Fix the type of <code>struct statvfs.f_fsid</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4576">#4576</a>)</li>
    <li>AIX: Fix the type of constants for the <code>ioctl</code>
    <code>request</code> argument (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4582">#4582</a>)</li>
    <li>AIX: Fix the types of <code>stat{,64}.st_*tim</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4597">#4597</a>)</li>
    <li>AIX: Use unique <code>errno</code> values (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4507">#4507</a>)</li>
    <li>Build: Fix an incorrect <code>target_os</code> -&gt;
    <code>target_arch</code> check (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4550">#4550</a>)</li>
    <li>FreeBSD: Fix the type of <code>xktls_session_onedir.ifnet</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4552">#4552</a>)</li>
    <li>Mips64 musl: Fix the type of <code>nlink_t</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4509">#4509</a>)</li>
    <li>Mips64 musl: Use a special MIPS definition of <code>stack_t</code>
    (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4528">#4528</a>)</li>
    <li>Mips64: Fix <code>SI_TIMER</code>, <code>SI_MESGQ</code> and
    <code>SI_ASYNCIO</code> definitions (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4529">#4529</a>)</li>
    <li>Musl Mips64: Swap the order of <code>si_errno</code> and
    <code>si_code</code> in <code>siginfo_t</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4530">#4530</a>)</li>
    <li>Musl Mips64: Use a special MIPS definition of <code>statfs</code>
    (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4527">#4527</a>)</li>
    <li>Musl: Fix the definition of <code>fanotify_event_metadata</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4510">#4510</a>)</li>
    <li>NetBSD: Correct <code>enum fae_action</code> to be
    <code>#[repr(C)]</code> (<a
    href="https://github.com/rust-lang/libc/commit/60a8cfd564f83164d45b9533ff7a0d7371878f2a">#60a8cfd5</a>)</li>
    <li>PSP: Correct <code>char</code> -&gt; <code>c_char</code> (<a
    href="https://github.com/rust-lang/libc/commit/eaab4fc3f05dc646a953d4fd5ba46dfa1f8bd6f6">eaab4fc3</a>)</li>
    <li>PowerPC musl: Fix <code>termios</code> definitions (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4518">#4518</a>)</li>
    <li>PowerPC musl: Fix the definition of <code>EDEADLK</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4517">#4517</a>)</li>
    <li>PowerPC musl: Fix the definition of <code>NCCS</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4513">#4513</a>)</li>
    <li>PowerPC musl: Fix the definitions of <code>MAP_LOCKED</code> and
    <code>MAP_NORESERVE</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4516">#4516</a>)</li>
    <li>PowerPC64 musl: Fix the definition of <code>shmid_ds</code> (<a
    href="https://redirect.github.com/rust-lang/libc/pull/4519">#4519</a>)</li>
    </ul>
    <!-- raw HTML omitted -->
    </blockquote>
    <p>... (truncated)</p>
    </details>
    <details>
    <summary>Commits</summary>
    <ul>
    <li><a
    href="https://github.com/rust-lang/libc/commit/84e26e6b166a6634d679fbf44e957102846b8a03"><code>84e26e6</code></a>
    Update the lockfile</li>
    <li><a
    href="https://github.com/rust-lang/libc/commit/4d04aee906450fed27305de30c23f518166f919f"><code>4d04aee</code></a>
    chore: release libc 0.2.175</li>
    <li><a
    href="https://github.com/rust-lang/libc/commit/94a7f32972a352fe348edbd49b06995542f3c5f5"><code>94a7f32</code></a>
    cleanup: Format a file that was missed</li>
    <li><a
    href="https://github.com/rust-lang/libc/commit/172527344a1d92b2ca7f88fe2b1bbde4b02de58b"><code>1725273</code></a>
    Rename the ctest file from <code>main</code> to <code>ctest</code></li>
    <li><a
    href="https://github.com/rust-lang/libc/commit/e9b021b7cd3d3f045ce8ec743d344e56b14f7244"><code>e9b021b</code></a>
    freebsd adding further TCP stack related constants.</li>
    <li><a
    href="https://github.com/rust-lang/libc/commit/9606a2918b1f370119af8022d61b0ff03175beb5"><code>9606a29</code></a>
    freebsd15: Add ki_uerrmsg to struct kinfo_proc</li>
    <li><a
    href="https://github.com/rust-lang/libc/commit/2816bc2f66c1c62ec5a616fb499a2b27bbba4a3c"><code>2816bc2</code></a>
    libc-test: include sys/ktls.h on freebsd</li>
    <li><a
    href="https://github.com/rust-lang/libc/commit/adfe283365cff1c6a05cddeca8afeaa667d1c637"><code>adfe283</code></a>
    libc-test: Account for xktls_session_onedir::gen (freebsd)</li>
    <li><a
    href="https://github.com/rust-lang/libc/commit/4cc1bf43310e6a31636e4c4eb31e78e702938f50"><code>4cc1bf4</code></a>
    freebsd: Document avoidance of reserved name <code>gen</code></li>
    <li><a
    href="https://github.com/rust-lang/libc/commit/7cdcaa62396816db2177cb663a4bf57f79603a52"><code>7cdcaa6</code></a>
    freebsd: Fix type of struct xktls_session_onedir, field ifnet</li>
    <li>Additional commits viewable in <a
    href="https://github.com/rust-lang/libc/compare/0.2.174...0.2.175">compare
    view</a></li>
    </ul>
    </details>
    <br />
    
    
    [![Dependabot compatibility
    score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=libc&package-manager=cargo&previous-version=0.2.174&new-version=0.2.175)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
    
    Dependabot will resolve any conflicts with this PR as long as you don't
    alter it yourself. You can also trigger a rebase manually by commenting
    `@dependabot rebase`.
    
    [//]: # (dependabot-automerge-start)
    [//]: # (dependabot-automerge-end)
    
    ---
    
    <details>
    <summary>Dependabot commands and options</summary>
    <br />
    
    You can trigger Dependabot actions by commenting on this PR:
    - `@dependabot rebase` will rebase this PR
    - `@dependabot recreate` will recreate this PR, overwriting any edits
    that have been made to it
    - `@dependabot merge` will merge this PR after your CI passes on it
    - `@dependabot squash and merge` will squash and merge this PR after
    your CI passes on it
    - `@dependabot cancel merge` will cancel a previously requested merge
    and block automerging
    - `@dependabot reopen` will reopen this PR if it is closed
    - `@dependabot close` will close this PR and stop Dependabot recreating
    it. You can achieve the same result by closing it manually
    - `@dependabot show <dependency name> ignore conditions` will show all
    of the ignore conditions of the specified dependency
    - `@dependabot ignore this major version` will close this PR and stop
    Dependabot creating any more for this major version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this minor version` will close this PR and stop
    Dependabot creating any more for this minor version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this dependency` will close this PR and stop
    Dependabot creating any more for this dependency (unless you reopen the
    PR or upgrade to it yourself)
    
    
    </details>
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • Auto format toml (#1745)
    Add recommended extension and configure it to auto format prompt.
  • feat: support dotenv (including ~/.codex/.env) (#1653)
    This PR adds a `load_dotenv()` helper function to the `codex-common`
    crate that is available when the `cli` feature is enabled. The function
    uses [`dotenvy`](https://crates.io/crates/dotenvy) to update the
    environment from:
    
    - `$CODEX_HOME/.env`
    - `$(pwd)/.env`
    
    To test:
    
    - ran `printenv OPENAI_API_KEY` to verify the env var exists in my
    environment
    - ran `just codex exec hello` to verify the CLI uses my `OPENAI_API_KEY`
    - ran `unset OPENAI_API_KEY`
    - ran `just codex exec hello` again and got **ERROR: Missing environment
    variable: `OPENAI_API_KEY`**, as expected
    - created `~/.codex/.env` and added `OPENAI_API_KEY=sk-proj-...` (also
    ran `chmod 400 ~/.codex/.env` for good measure)
    - ran `just codex exec hello` again and it worked, verifying it picked
    up `OPENAI_API_KEY` from `~/.codex/.env`
    
    Note this functionality was available in the TypeScript CLI:
    https://github.com/openai/codex/pull/122 and was recently requested over
    on https://github.com/openai/codex/issues/1262#issuecomment-3093203551.
  • feat: redesign sandbox config (#1373)
    This is a major redesign of how sandbox configuration works and aims to
    fix https://github.com/openai/codex/issues/1248. Specifically, it
    replaces `sandbox_permissions` in `config.toml` (and the
    `-s`/`--sandbox-permission` CLI flags) with a "table" with effectively
    three variants:
    
    ```toml
    # Safest option: full disk is read-only, but writes and network access are disallowed.
    [sandbox]
    mode = "read-only"
    
    # The cwd of the Codex task is writable, as well as $TMPDIR on macOS.
    # writable_roots can be used to specify additional writable folders.
    [sandbox]
    mode = "workspace-write"
    writable_roots = []  # Optional, defaults to the empty list.
    network_access = false  # Optional, defaults to false.
    
    # Disable sandboxing: use at your own risk!!!
    [sandbox]
    mode = "danger-full-access"
    ```
    
    This should make sandboxing easier to reason about. While we have
    dropped support for `-s`, the way it works now is:
    
    - no flags => `read-only`
    - `--full-auto` => `workspace-write`
    - currently, there is no way to specify `danger-full-access` via a CLI
    flag, but we will revisit that as part of
    https://github.com/openai/codex/issues/1254
    
    Outstanding issue:
    
    - As noted in the `TODO` on `SandboxPolicy::is_unrestricted()`, we are
    still conflating sandbox preferences with approval preferences in that
    case, which needs to be cleaned up.
  • fix: overhaul how we spawn commands under seccomp/landlock on Linux (#1086)
    Historically, we spawned the Seatbelt and Landlock sandboxes in
    substantially different ways:
    
    For **Seatbelt**, we would run `/usr/bin/sandbox-exec` with our policy
    specified as an arg followed by the original command:
    
    
    https://github.com/openai/codex/blob/d1de7bb383552e8fadd94be79d65d188e00fd562/codex-rs/core/src/exec.rs#L147-L219
    
    For **Landlock/Seccomp**, we would do
    `tokio::runtime::Builder::new_current_thread()`, _invoke
    Landlock/Seccomp APIs to modify the permissions of that new thread_, and
    then spawn the command:
    
    
    https://github.com/openai/codex/blob/d1de7bb383552e8fadd94be79d65d188e00fd562/codex-rs/core/src/exec_linux.rs#L28-L49
    
    While it is neat that Landlock/Seccomp supports applying a policy to
    only one thread without having to apply it to the entire process, it
    requires us to maintain two different codepaths and is a bit harder to
    reason about. The tipping point was
    https://github.com/openai/codex/pull/1061, in which we had to start
    building up the `env` in an unexpected way for the existing
    Landlock/Seccomp approach to continue to work.
    
    This PR overhauls things so that we do similar things for Mac and Linux.
    It turned out that we were already building our own "helper binary"
    comparable to Mac's `sandbox-exec` as part of the `cli` crate:
    
    
    https://github.com/openai/codex/blob/d1de7bb383552e8fadd94be79d65d188e00fd562/codex-rs/cli/Cargo.toml#L10-L12
    
    We originally created this to build a small binary to include with the
    Node.js version of the Codex CLI to provide support for Linux
    sandboxing.
    
    Though the sticky bit is that, at this point, we still want to deploy
    the Rust version of Codex as a single, standalone binary rather than a
    CLI and a supporting sandboxing binary. To satisfy this goal, we use
    "the arg0 trick," in which we:
    
    * use `std::env::current_exe()` to get the path to the CLI that is
    currently running
    * use the CLI as the `program` for the `Command`
    * set `"codex-linux-sandbox"` as arg0 for the `Command`
    
    A CLI that supports sandboxing should check arg0 at the start of the
    program. If it is `"codex-linux-sandbox"`, it must invoke
    `codex_linux_sandbox::run_main()`, which runs the CLI as if it were
    `codex-linux-sandbox`. When acting as `codex-linux-sandbox`, we make the
    appropriate Landlock/Seccomp API calls and then use `execvp(3)` to spawn
    the original command, so do _replace_ the process rather than spawn a
    subprocess. Incidentally, we do this before starting the Tokio runtime,
    so the process should only have one thread when `execvp(3)` is called.
    
    Because the `core` crate that needs to spawn the Linux sandboxing is not
    a CLI in its own right, this means that every CLI that includes `core`
    and relies on this behavior has to (1) implement it and (2) provide the
    path to the sandboxing executable. While the path is almost always
    `std::env::current_exe()`, we needed to make this configurable for
    integration tests, so `Config` now has a `codex_linux_sandbox_exe:
    Option<PathBuf>` property to facilitate threading this through,
    introduced in https://github.com/openai/codex/pull/1089.
    
    This common pattern is now captured in
    `codex_linux_sandbox::run_with_sandbox()` and all of the `main.rs`
    functions that should use it have been updated as part of this PR.
    
    The `codex-linux-sandbox` crate added to the Cargo workspace as part of
    this PR now has the bulk of the Landlock/Seccomp logic, which makes
    `core` a bit simpler. Indeed, `core/src/exec_linux.rs` and
    `core/src/landlock.rs` were removed/ported as part of this PR. I also
    moved the unit tests for this code into an integration test,
    `linux-sandbox/tests/landlock.rs`, in which I use
    `env!("CARGO_BIN_EXE_codex-linux-sandbox")` as the value for
    `codex_linux_sandbox_exe` since `std::env::current_exe()` is not
    appropriate in that case.