Commit Graph

51 Commits

  • add a slash command to grant sandbox read access to inaccessible directories (#11512)
    There is an edge case where a directory is not readable by the sandbox.
    In practice, we've seen very little of it, but it can happen so this
    slash command unlocks users when it does.
    
    Future idea is to make this a tool that the agent knows about so it can
    be more integrated.
  • feat: make sandbox read access configurable with ReadOnlyAccess (#11387)
    `SandboxPolicy::ReadOnly` previously implied broad read access and could
    not express a narrower read surface.
    This change introduces an explicit read-access model so we can support
    user-configurable read restrictions in follow-up work, while preserving
    current behavior today.
    
    It also ensures unsupported backends fail closed for restricted-read
    policies instead of silently granting broader access than intended.
    
    ## What
    
    - Added `ReadOnlyAccess` in protocol with:
      - `Restricted { include_platform_defaults, readable_roots }`
      - `FullAccess`
    - Updated `SandboxPolicy` to carry read-access configuration:
      - `ReadOnly { access: ReadOnlyAccess }`
      - `WorkspaceWrite { ..., read_only_access: ReadOnlyAccess }`
    - Preserved existing behavior by defaulting current construction paths
    to `ReadOnlyAccess::FullAccess`.
    - Threaded the new fields through sandbox policy consumers and call
    sites across `core`, `tui`, `linux-sandbox`, `windows-sandbox`, and
    related tests.
    - Updated Seatbelt policy generation to honor restricted read roots by
    emitting scoped read rules when full read access is not granted.
    - Added fail-closed behavior on Linux and Windows backends when
    restricted read access is requested but not yet implemented there
    (`UnsupportedOperation`).
    - Regenerated app-server protocol schema and TypeScript artifacts,
    including `ReadOnlyAccess`.
    
    ## Compatibility / rollout
    
    - Runtime behavior remains unchanged by default (`FullAccess`).
    - API/schema changes are in place so future config wiring can enable
    restricted read access without another policy-shape migration.
  • fix: remove errant Cargo.lock files (#11526)
    These leaked into the repo:
    
    - #4905 `codex-rs/windows-sandbox-rs/Cargo.lock`
    - #5391 `codex-rs/app-server-test-client/Cargo.lock`
    
    Note that these affect cache keys such as:
    
    
    https://github.com/openai/codex/blob/9722567a80b4bac81b74f679828747031fd95fa0/.github/workflows/rust-release.yml#L154
    
    so it seems best to remove them.
  • Promote Windows Sandbox (#11341)
    1. Move Windows Sandbox NUX to right after trust directory screen
    2. Don't offer read-only as an option in Sandbox NUX.
    Elevated/Legacy/Quit
    3. Don't allow new untrusted directories. It's trust or quit
    4. move experimental sandbox features to `[windows]
    sandbox="elevated|unelevatd"`
    5. Copy tweaks = elevated -> default, non-elevated -> non-admin
  • Include real OS info in metrics. (#10425)
    calculated a hashed user ID from either auth user id or API key
    Also correctly populates OS.
    
    These will make our metrics more useful and powerful for analysis.
  • implement per-workspace capability SIDs for workspace specific ACLs (#10189)
    Today, there is a single capability SID that allows the sandbox to write
    to
    * workspace (cwd)
    * tmp directories if enabled
    * additional writable roots
    
    This change splits those up, so that each workspace has its own
    capability SID, while tmp and additional roots, which are
    installation-wide, are still governed by the "generic" capability SID
    
    This isolates workspaces from each other in terms of sandbox write
    access.
    Also allows us to protect <cwd>/.codex when codex runs in a specific
    <cwd>
  • emit a separate metric when the user cancels UAT during elevated setup (#10399)
    Currently this shows up as elevated setup failure, which isn't quite
    accurate.
  • fix: handle utf-8 in windows sandbox logs (#8647)
    Currently `apply_patch` will fail on Windows if the file contents happen
    to have a multi-byte character at the point where the `preview` function
    truncates.
    
    I've used the existing `take_bytes_at_char_boundary` helper and added a
    regression test (that fails without the fix).
    
    This is related to #4013 but doesn't fix it.
  • fix(windows-sandbox): remove request files after read (#9316)
    ## Summary
    - Remove elevated runner request files after read (best-effort cleanup
    on errors)
    - Add a unit test to cover request file lifecycle
    
    ## Testing
    - `cargo test -p codex-windows-sandbox` (Windows)
    
    Fixes #9315
  • use machine scope instead of user scope for dpapi. (#9713)
    This fixes a bug where the elevated sandbox setup encrypts sandbox user
    passwords as an admin user, but normal command execution attempts to
    decrypt them as a different user.
    
    Machine scope allows all users to encyrpt/decrypt
    
    this PR also moves the encrypted file to a different location
    .codex/.sandbox-secrets which the sandbox users cannot read.
  • fix(windows-sandbox): parse PATH list entries for audit roots (#9319)
    ## Summary
    - Use `std::env::split_paths` to parse PATH entries in audit candidate
    collection
    - Add a unit test covering multiple PATH entries (including spaces)
    
    ## Testing
    - `cargo test -p codex-windows-sandbox` (Windows)
    
    Fixes #9317
  • fix(windows-sandbox): deny .git file entries under writable roots (#9314)
    ## Summary
    - Deny `.git` entries under writable roots even when `.git` is a file
    (worktrees/submodules)
    - Add a unit test for `.git` file handling
    
    ## Testing
    - `cargo test -p codex-windows-sandbox` (Windows)
    
    Fixes #9313
  • lookup system SIDs instead of hardcoding English strings. (#9552)
    The elevated setup does not work on non-English windows installs where
    Users/Administrators/etc are in different languages. This PR uses the
    well-known SIDs instead, which do not vary based on locale
  • chore: upgrade to Rust 1.92.0 (#8860)
    **Summary**
    - Upgrade Rust toolchain used by CI to 1.92.0.
    - Address new clippy `derivable_impls` warnings by deriving `Default`
    for enums across protocol, core, backend openapi models, and
    windows-sandbox setup.
    - Tidy up related test/config behavior (originator header handling, env
    override cleanup) and remove a now-unused assignment in TUI/TUI2 render
    layout.
    
    **Testing**
    - `just fmt`
    - `just fix -p codex-tui`
    - `just fix -p codex-tui2`
    - `just fix -p codex-windows-sandbox`
    - `cargo test -p codex-tui`
    - `cargo test -p codex-tui2`
    - `cargo test -p codex-windows-sandbox`
    - `cargo test -p codex-core --test all`
    - `cargo test -p codex-app-server --test all`
    - `cargo test -p codex-mcp-server --test all`
    - `cargo test --all-features`
  • fix(windows-sandbox-rs) bump SETUP_VERSION (#9134)
    ## Summary
    Bumps the windows setup version, to re-trigger windows sandbox setup for
    users in the experimental sandbox. We've seen some drift in the ACL
    controls, amongst a few other changes. Hopefully this should fix #9062.
    
    ## Testing
    - [x] Tested locally
  • feat: add support for building with Bazel (#8875)
    This PR configures Codex CLI so it can be built with
    [Bazel](https://bazel.build) in addition to Cargo. The `.bazelrc`
    includes configuration so that remote builds can be done using
    [BuildBuddy](https://www.buildbuddy.io).
    
    If you are familiar with Bazel, things should work as you expect, e.g.,
    run `bazel test //... --keep-going` to run all the tests in the repo,
    but we have also added some new aliases in the `justfile` for
    convenience:
    
    - `just bazel-test` to run tests locally
    - `just bazel-remote-test` to run tests remotely (currently, the remote
    build is for x86_64 Linux regardless of your host platform). Note we are
    currently seeing the following test failures in the remote build, so we
    still need to figure out what is happening here:
    
    ```
    failures:
        suite::compact::manual_compact_twice_preserves_latest_user_messages
        suite::compact_resume_fork::compact_resume_after_second_compaction_preserves_history
        suite::compact_resume_fork::compact_resume_and_fork_preserve_model_history_view
    ```
    
    - `just build-for-release` to build release binaries for all
    platforms/architectures remotely
    
    To setup remote execution:
    - [Create a buildbuddy account](https://app.buildbuddy.io/) (OpenAI
    employees should also request org access at
    https://openai.buildbuddy.io/join/ with their `@openai.com` email
    address.)
    - [Copy your API key](https://app.buildbuddy.io/docs/setup/) to
    `~/.bazelrc` (add the line `build
    --remote_header=x-buildbuddy-api-key=YOUR_KEY`)
    - Use `--config=remote` in your `bazel` invocations (or add `common
    --config=remote` to your `~/.bazelrc`, or use the `just` commands)
    
    ## CI
    
    In terms of CI, this PR introduces `.github/workflows/bazel.yml`, which
    uses Bazel to run the tests _locally_ on Mac and Linux GitHub runners
    (we are working on supporting Windows, but that is not ready yet). Note
    that the failures we are seeing in `just bazel-remote-test` do not occur
    on these GitHub CI jobs, so everything in `.github/workflows/bazel.yml`
    is green right now.
    
    The `bazel.yml` uses extra config in `.github/workflows/ci.bazelrc` so
    that macOS CI jobs build _remotely_ on Linux hosts (using the
    `docker://docker.io/mbolin491/codex-bazel` Docker image declared in the
    root `BUILD.bazel`) using cross-compilation to build the macOS
    artifacts. Then these artifacts are downloaded locally to GitHub's macOS
    runner so the tests can be executed natively. This is the relevant
    config that enables this:
    
    ```
    common:macos --config=remote
    common:macos --strategy=remote
    common:macos --strategy=TestRunner=darwin-sandbox,local
    ```
    
    Because of the remote caching benefits we get from BuildBuddy, these new
    CI jobs can be extremely fast! For example, consider these two jobs that
    ran all the tests on Linux x86_64:
    
    - Bazel 1m37s
    https://github.com/openai/codex/actions/runs/20861063212/job/59940545209?pr=8875
    - Cargo 9m20s
    https://github.com/openai/codex/actions/runs/20861063192/job/59940559592?pr=8875
    
    For now, we will continue to run both the Bazel and Cargo jobs for PRs,
    but once we add support for Windows and running Clippy, we should be
    able to cutover to using Bazel exclusively for PRs, which should still
    speed things up considerably. We will probably continue to run the Cargo
    jobs post-merge for commits that land on `main` as a sanity check.
    
    Release builds will also continue to be done by Cargo for now.
    
    Earlier attempt at this PR: https://github.com/openai/codex/pull/8832
    Earlier attempt to add support for Buck2, now abandoned:
    https://github.com/openai/codex/pull/8504
    
    ---------
    
    Co-authored-by: David Zbarsky <dzbarsky@gmail.com>
    Co-authored-by: Michael Bolin <mbolin@openai.com>
  • Elevated sandbox NUX (#8789)
    Elevated Sandbox NUX:
    
    * prompt for elevated sandbox setup when agent mode is selected (via
    /approvals or at startup)
    * prompt for degraded sandbox if elevated setup is declined or fails
    * introduce /elevate-sandbox command to upgrade from degraded
    experience.
  • best effort to "hide" Sandbox users (#8492)
    The elevated sandbox creates two new Windows users - CodexSandboxOffline
    and CodexSandboxOnline. This is necessary, so this PR does all that it
    can to "hide" those users. It uses the registry plus directory flags (on
    their home directories) to get them to show up as little as possible.
  • never let sandbox write to .codex/ or .codex/.sandbox/ (#8683)
    Never treat .codex or .codex/.sandbox as a workspace root.
    Handle write permissions to .codex/.sandbox in a single method so that
    the sandbox setup/runner can write logs and other setup files to that
    directory.
  • better idempotency for creating/updating firewall rules during setup. (#8686)
    make sure if the Sandbox has to re-initialize with different Sandbox
    user SID, it still finds/updates the firewall rule instead of creating a
    new one.
  • use a SandboxUsers group for ACLs instead of granting to each sandbox user separately (#8483)
    This is more future-proof if we ever decide to add additional Sandbox
    Users for new functionality
    
    This also moves some more user-related code into a new file for code
    cleanliness
  • fix: restrict windows-sys to Windows target (#8522)
    I attempted to build codex on LoongArch Linux and encountered
    compilation errors.
    After investigation, the errors were traced to certain `windows-sys`
    features
    which rely on platform-specific cfgs that only support x86 and aarch64.
    
    With this change applied, the project now builds and runs successfully
    on my
    platform:
    - OS: AOSC OS (loongarch64)
    - Kernel: Linux 6.17
    - CPU: Loongson-3A6000
    
    Please let me know if this approach is reasonable, or if there is a
    better way
    to support additional platforms.
  • use a junction for the cwd while read ACLs are being applied (#8444)
    The elevated setup synchronously applies read/write ACLs to any
    workspace roots.
    
    However, until we apply *read* permission to the full path, powershell
    cannot use some roots as a cwd as it needs access to all parts of the
    path in order to apply it as the working directory for a command.
    
    The solution is, while the async read-ACL part of setup is running, use
    a "junction" that lives in C:\Users\CodexSandbox{Offline|Online} that
    points to the cwd.
    
    Once the read ACLs are applied, we stop using the junction.
    
    -----
    
    this PR also removes some dead code and overly-verbose logging, and has
    some light refactoring to the ACL-related functions
  • feat: introduce ExternalSandbox policy (#8290)
    ## Description
    
    Introduced `ExternalSandbox` policy to cover use case when sandbox
    defined by outside environment, effectively it translates to
    `SandboxMode#DangerFullAccess` for file system (since sandbox configured
    on container level) and configurable `network_access` (either Restricted
    or Enabled by outside environment).
    
    as example you can configure `ExternalSandbox` policy as part of
    `sendUserTurn` v1 app_server API:
    
    ```
     {
                "conversationId": <id>,
                "cwd": <cwd>,
                "approvalPolicy": "never",
                "sandboxPolicy": {
                      "type": ""external-sandbox",
                      "network_access": "enabled"/"restricted"
                },
                "model": <model>,
                "effort": <effort>,
                ....
            }
    ```
  • add a default dacl to restricted token to enable reading of pipes (#8280)
    this fixes sandbox errors (legacy and elevated) for commands that
    include pipes, which the model often favors.
  • grant read ACL to exe directory first so we can call the command runner (#8275)
    when granting read access to the sandbox user, grant the
    codex/command-runner exe directory first so commands can run before the
    entire read ACL process is finished.
  • speed and reliability improvements for setting reads ACLs (#8216)
    - Batch read ACL creation for online/offline sandbox user
    - creates a new ACL helper process that is long-lived and runs in the
    background
    - uses a mutex so that only one helper process is running at a time.
  • bug fixes and perf improvements for elevated sandbox setup (#8094)
    a few fixes based on testing feedback:
    * ensure cap_sid file is always written by elevated setup.
    * always log to same file whether using elevated sandbox or not
    * process potentially slow ACE write operations in parallel
    * dedupe write roots so we don't double process any
    * don't try to create read/write ACEs on the same directories, due to
    race condition
  • 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.
  • Elevated Sandbox 3 (#7809)
    dedicated sandbox command runner exe.
  • Elevated Sandbox 2 (#7792)
    - DPAPI helpers for storing Sandbox user passwords securely
    - creation of Offline/Online sandbox users
    - ACL setup for sandbox users
    - firewall rule setup
  • Elevated Sandbox 1 (#7788)
    - updating helpers, refactoring some functions that will be used in the
    elevated sandbox
    - better logging
    - better and faster handling of ACL checks/writes
    - No functional change—legacy restricted-token sandbox
    remains the only path.
  • Windows Sandbox: treat <workspace_root>/.git as read-only in workspace-write mode (#7142)
    this functionality is
    [supported](https://github.com/openai/codex/blob/main/codex-rs/protocol/src/protocol.rs#L421-L422)
    in the MacOs sandbox as well. Adding it to Windows for parity
    
    This PR also changes `rust-ci.yaml` to work around a github `hashFiles`
    issue. Others have done something
    [similar](https://github.com/openai/superassistant/pull/32156) today
  • 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
  • consolidate world-writable-directories scanning. (#7234)
    clean up the code for scanning for world writable directories
    
    One path (selecting a sandbox mode from /approvals) was using an
    incorrect method that did not use the new method of creating deny aces
    to prevent writing to those directories. Now all paths are the same.
  • add deny ACEs for world writable dirs (#7022)
    Our Restricted Token contains 3 SIDs (Logon, Everyone, {WorkspaceWrite
    Capability || ReadOnly Capability})
    
    because it must include Everyone, that left us vulnerable to directories
    that allow writes to Everyone. Even though those directories do not have
    ACEs that enable our capability SIDs to write to them, they could still
    be written to even in ReadOnly mode, or even in WorkspaceWrite mode if
    they are outside of a writable root.
    
    A solution to this is to explicitly add *Deny* ACEs to these
    directories, always for the ReadOnly Capability SID, and for the
    WorkspaceWrite SID if the directory is outside of a workspace root.
    
    Under a restricted token, Windows always checks Deny ACEs before Allow
    ACEs so even though our restricted token would allow a write to these
    directories due to the Everyone SID, it fails first because of the Deny
    ACE on the capability SID
  • stop over-reporting world-writable directories (#6936)
    Fix world-writable audit false positives by expanding generic
    permissions with MapGenericMask and then checking only concrete write
    bits. The earlier check looked for FILE_GENERIC_WRITE/generic masks
    directly, which shares bits with read permissions and could flag an
    Everyone read ACE as writable.
  • have world_writable_warning_details accept cwd as a param (#6913)
    this enables app-server to pass in the correct workspace cwd for the
    current conversation
  • windows sandbox: support multiple workspace roots (#6854)
    The Windows sandbox did not previously support multiple workspace roots
    via config. Now it does
  • Prompt to turn on windows sandbox when auto mode selected. (#6618)
    - stop prompting users to install WSL 
    - prompt users to turn on Windows sandbox when auto mode requested.
    
    <img width="1660" height="195" alt="Screenshot 2025-11-17 110612"
    src="https://github.com/user-attachments/assets/c67fc239-a227-417e-94bb-599a8ed8f11e"
    />
    <img width="1684" height="168" alt="Screenshot 2025-11-17 110637"
    src="https://github.com/user-attachments/assets/d18c3370-830d-4971-8746-04757ae2f709"
    />
    <img width="1655" height="293" alt="Screenshot 2025-11-17 110719"
    src="https://github.com/user-attachments/assets/d21f6ce9-c23e-4842-baf6-8938b77c16db"
    />
  • move cap_sid file into ~/.codex so the sandbox cannot overwrite it (#6798)
    The `cap_sid` file contains the IDs of the two custom SIDs that the
    Windows sandbox creates/manages to implement read-only and
    workspace-write sandbox policies.
    
    It previously lived in `<cwd>/.codex` which means that the sandbox could
    write to it, which could degrade the efficacy of the sandbox. This
    change moves it to `~/.codex/` (or wherever `CODEX_HOME` points to) so
    that it is outside the workspace.
  • fix codex detection, add new security-focused smoketests. (#6682)
    Fix 'codex' detection to look for debug build, then release build, then
    installed.
    
    Adds more smoketests around security from @viyatb-oai
  • more world-writable warning improvements (#6389)
    3 improvements:
    1. show up to 3 actual paths that are world-writable
    2. do the scan/warning for Read-Only mode too, because it also applies
    there
    3. remove the "Cancel" option since it doesn't always apply (like on
    startup)
  • Improve world-writable scan (#6381)
    1. scan many more directories since it's much faster than the original
    implementation
    2. limit overall scan time to 2s
    3. skip some directories that are noisy - ApplicationData, Installer,
    etc.
  • Windows Sandbox: Show Everyone-writable directory warning (#6283)
    Show a warning when Auto Sandbox mode becomes enabled, if we detect
    Everyone-writable directories, since they cannot be protected by the
    current implementation of the Sandbox.
    
    This PR also includes changes to how we detect Everyone-writable to be
    *much* faster
  • log sandbox commands to $CODEX_HOME instead of cwd (#6171)
    Logging commands in the Windows Sandbox is temporary, but while we are
    doing it, let's always write to CODEX_HOME instead of dirtying the cwd.