viyatb-oai
viyatb@openai.com
90d · built 2026-05-28
90-day totals
- Commits
- 89
- Grow
- 11.8
- Maintenance
- 9.9
- Fixes
- 16.5
- Total ETV
- 38.2
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 97 %
- By Growth share
- Top 27 %
30-day trajectory
Last 30 days vs. the 30 days before. Up arrows on Growth and ETV mean improvement; up arrow on Fixes share means more time on fixes (worse).
Daily performance
Daily ETV, stacked by Growth, Maintenance and Fixes.
Work-mix over time
Share of Growth / Maintenance / Fixes over a rolling 7-day window. Reads as 'where is effort flowing right now'.
Bug flow over time
Monthly bug flow attributed to this developer. The left bar (red) is bug impact this dev authored that was addressed in the given month — combining bugs others fixed for them and bugs they fixed themselves. The right bar is fixes they personally shipped that month, split between self-fixes (overlap with the red bar) and fixes done for someone else. X-axis is fix-time, not introduction-time — the Navigara API attributes bugs backward to the author at the moment the fix lands.
- Self-fix share
- 29%
- Bugs you introduced
- 7.2
- Bugs you fixed
- 19.1
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 20 by ETV in the 90-day window.
- 3.2ETVfix: handle deferred network proxy denials (#19184) ## Why This bug is exposed by Guardian/auto-review approvals. With the managed network proxy enabled, a blocked network request can be reported back through the network approval service as an approval denial after the command has already started. Before this change, the shell and unified exec runtimes registered those network approval calls, but did not have a way to observe an async proxy denial as a cancellation/failure signal for the running process. The result was confusing: Guardian/auto-review could correctly deny network access, but the command path could keep running or unregister the approval without surfacing the denial as the command failure. ## What Changed - `NetworkApprovalService` now attaches a cancellation token to active and deferred network approvals. - Proxy-denial outcomes are recorded only for active registrations, cancel the owning token, and are consumed when the approval is finalized. - The shell runtime combines the normal command timeout with the network-denial cancellation token. - Unified exec stores the deferred network approval object, terminates tracked processes when the proxy denial arrives, and returns the denial as a process failure while polling or completing the process. - Tool orchestration passes the active network approval cancellation token into the sandbox attempt and preserves deferred approval errors instead of silently unregistering them. - App-server `command/exec` now handles the combined timeout-or-cancellation expiration variant used by the runtime. ## Verification - `cargo test -p codex-core network_approval --lib` - `cargo clippy -p codex-app-server --all-targets -- -D warnings` - `cargo clippy -p codex-core --all-targets -- -D warnings` --------- Co-authored-by: Codex <noreply@openai.com>github.com-openai-codex · 07c8b8c7 · 2026-04-29
- 1.7ETVfeat(sandbox): add Windows deny-read parity (#18202) ## Why The split filesystem policy stack already supports exact and glob `access = none` read restrictions on macOS and Linux. Windows still needed subprocess handling for those deny-read policies without claiming enforcement from a backend that cannot provide it. ## Key finding The unelevated restricted-token backend cannot safely enforce deny-read overlays. Its `WRITE_RESTRICTED` token model is authoritative for write checks, not read denials, so this PR intentionally fails that backend closed when deny-read overrides are present instead of claiming unsupported enforcement. ## What changed This PR adds the Windows deny-read enforcement layer and makes the backend split explicit: - Resolves Windows deny-read filesystem policy entries into concrete ACL targets. - Preserves exact missing paths so they can be materialized and denied before an enforceable sandboxed process starts. - Snapshot-expands existing glob matches into ACL targets for Windows subprocess enforcement. - Honors `glob_scan_max_depth` when expanding Windows deny-read globs. - Plans both the configured lexical path and the canonical target for existing paths so reparse-point aliases are covered. - Threads deny-read overrides through the elevated/logon-user Windows sandbox backend and unified exec. - Applies elevated deny-read ACLs synchronously before command launch rather than delegating them to the background read-grant helper. - Reconciles persistent deny-read ACEs per sandbox principal so policy changes do not leave stale deny-read ACLs behind. - Fails closed on the unelevated restricted-token backend when deny-read overrides are present, because its `WRITE_RESTRICTED` token model is not authoritative for read denials. ## Landed prerequisites These prerequisite PRs are already on `main`: 1. #15979 `feat(permissions): add glob deny-read policy support` 2. #18096 `feat(sandbox): add glob deny-read platform enforcement` 3. #17740 `feat(config): support managed deny-read requirements` This PR targets `main` directly and contains only the Windows deny-read enforcement layer. ## Implementation notes - Exact deny-read paths remain enforceable on the elevated path even when they do not exist yet: Windows materializes the missing path before applying the deny ACE, so the sandboxed command cannot create and read it during the same run. - Existing exact deny paths are preserved lexically until the ACL planner, which then adds the canonical target as a second ACL target when needed. That keeps both the configured alias and the resolved object covered. - Windows ACLs do not consume Codex glob syntax directly, so glob deny-read entries are expanded to the concrete matches that exist before process launch. - Glob traversal deduplicates directory visits within each pattern walk to avoid cycles, without collapsing distinct lexical roots that happen to resolve to the same target. - Persistent deny-read ACL state is keyed by sandbox principal SID, so cleanup only removes ACEs owned by the same backend principal. - Deny-read ACEs are fail-closed on the elevated path: setup aborts if mandatory deny-read ACL application fails. - Unelevated restricted-token sessions reject deny-read overrides early instead of running with a silently unenforceable read policy. ## Verification - `cargo test -p codex-core windows_restricted_token_rejects_unreadable_split_carveouts` - `just fmt` - `just fix -p codex-core` - `just fix -p codex-windows-sandbox` - GitHub Actions rerun is in progress on the pushed head. --------- Co-authored-by: Codex <noreply@openai.com>github.com-openai-codex · 46f30d02 · 2026-05-12
- 1.7ETVfix(permissions): fix symlinked writable roots in sandbox permissions (#15981) ## Summary - preserve logical symlink paths during permission normalization and config cwd handling - bind real targets for symlinked readable/writable roots in bwrap and remap carveouts and unreadable roots there - add regressions for symlinked carveouts and nested symlink escape masking ## Root cause Permission normalization canonicalized symlinked writable roots and cwd to their real targets too early. That drifted policy checks away from the logical paths the sandboxed process can actually address, while bwrap still needed the real targets for mounts. The mismatch caused shell and apply_patch failures on symlinked writable roots. ## Impact Fixes #15781. Also fixes #17079: - #17079 is the protected symlinked carveout side: bwrap now binds the real symlinked writable-root target and remaps carveouts before masking. Related to #15157: - #15157 is the broader permission-check side of this path-identity problem. This PR addresses the shared logical-vs-canonical normalization issue, but the reported Darwin prompt behavior should be validated separately before auto-closing it. This should also fix #14672, #14694, #14715, and #15725: - #14672, #14694, and #14715 are the same Linux symlinked-writable-root/bwrap family as #15781. - #15725 is the protected symlinked workspace path variant; the PR preserves the protected logical path in policy space while bwrap applies read-only or unreadable treatment to the resolved target so file-vs-directory bind mismatches do not abort sandbox setup. ## Notes - Added Linux-only regressions for symlinked writable ancestors and protected symlinked directory targets, including nested symlink escape masking without rebinding the escape target writable. --------- Co-authored-by: Codex <noreply@openai.com>github.com-openai-codex · b1147814 · 2026-04-11
- 1.6ETVfix: 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>github.com-openai-codex · 937cb508 · 2026-03-26
- 1.4ETVfix: align core approvals with split sandbox policies (#14171) ## Stack fix: fail closed for unsupported split windows sandboxing #14172 fix: preserve split filesystem semantics in linux sandbox #14173 -> fix: align core approvals with split sandbox policies #14171 refactor: centralize filesystem permissions precedence #14174 ## Why This PR Exists This PR is intentionally narrower than the title may suggest. Most of the original split-permissions migration already landed in the earlier `#13434 -> #13453` stack. In particular: - `#13439` already did the broad runtime plumbing for split filesystem and network policies. - `#13445` already moved `apply_patch` safety onto filesystem-policy semantics. - `#13448` already switched macOS Seatbelt generation to split policies. - `#13449` and `#13453` already handled Linux helper and bubblewrap enforcement. - `#13440` already introduced the first protocol-side helpers for deriving effective filesystem access. The reason this PR still exists is that after the follow-on `[permissions]` work and the new shared precedence helper in `#14174`, a few core approval paths were still deciding behavior from the legacy `SandboxPolicy` projection instead of the split filesystem policy that actually carries the carveouts. That means this PR is mostly a cleanup and alignment pass over the remaining core consumers, not a fresh sandbox backend migration. ## What Is Actually New Here - make unmatched-command fallback decisions consult `FileSystemSandboxPolicy` instead of only legacy `DangerFullAccess` / `ReadOnly` / `WorkspaceWrite` categories - thread `file_system_sandbox_policy` into the shell, unified-exec, and intercepted-exec approval paths so they all use the same split-policy semantics - keep `apply_patch` safety on the same effective-access rules as the shared protocol helper, rather than letting it drift through compatibility projections - add loader-level regression coverage proving legacy `sandbox_mode` config still builds split policies and round-trips back without semantic drift ## What This PR Does Not Do This PR does not introduce new platform backend enforcement on its own. - Linux backend parity remains in `#14173`. - Windows fail-closed handling remains in `#14172`. - The shared precedence/model changes live in `#14174`. ## Files To Focus On - `core/src/exec_policy.rs`: unmatched-command fallback and approval rendering now read the split filesystem policy directly - `core/src/tools/sandboxing.rs`: default exec-approval requirement keys off `FileSystemSandboxPolicy.kind` - `core/src/tools/handlers/shell.rs`: shell approval requests now carry the split filesystem policy - `core/src/unified_exec/process_manager.rs`: unified-exec approval requests now carry the split filesystem policy - `core/src/tools/runtimes/shell/unix_escalation.rs`: intercepted exec fallback now uses the same split-policy approval semantics - `core/src/safety.rs`: `apply_patch` safety keeps using effective filesystem access rather than legacy sandbox categories - `core/src/config/config_tests.rs`: new regression coverage for legacy `sandbox_mode` no-drift behavior through the split-policy loader ## Notes - `core/src/codex.rs` and `core/src/codex_tests.rs` are just small fallout updates for `RequestPermissionsResponse.scope`; they are not the point of the PR. - If you reviewed the earlier `#13439` / `#13445` stack, the main review question here is simply: “are there any remaining approval or patch-safety paths that still reconstruct semantics from legacy `SandboxPolicy` instead of consuming the split filesystem policy directly?” ## Testing - cargo test -p codex-core legacy_sandbox_mode_config_builds_split_policies_without_drift - cargo test -p codex-core request_permissions - cargo test -p codex-core intercepted_exec_policy - cargo test -p codex-core restricted_sandbox_requires_exec_approval_on_request - cargo test -p codex-core unmatched_on_request_uses_split_filesystem_policy_for_escalation_prompts - cargo test -p codex-core explicit_ - cargo clippy -p codex-core --tests -- -D warningsgithub.com-openai-codex · c2d5458d · 2026-03-12
- 1.3ETVfeat(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>github.com-openai-codex · 0d0abe83 · 2026-04-17
- 1.3ETVfix: trust-gate project hooks and exec policies (#14718) ## Summary - trust-gate project `.codex` layers consistently, including repos that have `.codex/hooks.json` or `.codex/execpolicy/*.rules` but no `.codex/config.toml` - keep disabled project layers in the config stack so nested trusted project layers still resolve correctly, while preventing hooks and exec policies from loading until the project is trusted - update app-server/TUI onboarding copy to make the trust boundary explicit and add regressions for loader, hooks, exec-policy, and onboarding coverage ## Security Before this change, an untrusted repo could auto-load project hooks or exec policies from `.codex/` as long as `config.toml` was absent. This makes trust the single gate for project-local config, hooks, and exec policies. ## Stack - Parent of #15936 ## Test - cargo test -p codex-core without_config_toml --------- Co-authored-by: Codex <noreply@openai.com>github.com-openai-codex · 370bed4b · 2026-04-18
- 1.2ETVfeat(windows-sandbox): add network proxy support (#12220) ## Summary This PR makes Windows sandbox proxying enforceable by routing proxy-only runs through the existing `offline` sandbox user and reserving direct network access for the existing `online` sandbox user. In brief: - if a Windows sandbox run should be proxy-enforced, we run it as the `offline` user - the `offline` user gets firewall rules that block direct outbound traffic and only permit the configured localhost proxy path - if a Windows sandbox run should have true direct network access, we run it as the `online` user - no new sandbox identity is introduced This brings Windows in line with the intended model: proxy use is not just env-based, it is backed by OS-level egress controls. Windows already has two sandbox identities: - `offline`: intended to have no direct network egress - `online`: intended to have full network access This PR makes proxy-enforced runs use that model directly. ### Proxy-enforced runs When proxy enforcement is active: - the run is assigned to the `offline` identity - setup extracts the loopback proxy ports from the sandbox env - Windows setup programs firewall rules for the `offline` user that: - block all non-loopback outbound traffic - block loopback UDP - block loopback TCP except for the configured proxy ports - optionally allow broader localhost access when `allow_local_binding=1` So the sandboxed process can only talk to the local proxy. It cannot open direct outbound sockets or do local UDP-based DNS on its own.The proxy then performs the real outbound network access outside that restricted sandbox identity. ### Direct-network runs When proxy enforcement is not active and full network access is allowed: - the run is assigned to the `online` identity - no proxy-only firewall restrictions are applied - the process gets normal direct network access ### Unelevated vs elevated The restricted-token / unelevated path cannot enforce per-identity firewall policy by itself. So for Windows proxy-enforced runs, we transparently use the logon-user sandbox path under the hood, even if the caller started from the unelevated mode. That keeps enforcement real instead of best-effort. --------- Co-authored-by: Codex <noreply@openai.com>github.com-openai-codex · 81fa0478 · 2026-03-27
- 1.2ETVfix: honor active permission profiles in sandbox debug (#14293) ## Summary - stop `codex sandbox` from forcing legacy `sandbox_mode` when active `[permissions]` profiles are configured - keep the legacy `read-only` / `workspace-write` fallback for legacy configs and reject `--full-auto` for profile-based configs - use split filesystem and network policies in the macOS/Linux debug sandbox helpers and add regressions for the config-loading behavior assuming "codex/docs/private/secret.txt" = "none" ``` codex -c 'default_permissions="limited-read-test"' sandbox macos -- <command> ... codex sandbox macos -- cat codex/docs/private/secret.txt >/dev/null; echo EXIT:$? cat: codex/docs/private/secret.txt: Operation not permitted EXIT:1 ``` --------- Co-authored-by: celia-oai <celia@openai.com>github.com-openai-codex · 6fe8a05d · 2026-03-18
- 1.2ETVfeat(permissions): add glob deny-read policy support (#15979) ## Summary - adds first-class filesystem policy entries for deny-read glob patterns - parses config such as :project_roots { "**/*.env" = "none" } into pattern entries - enforces deny-read patterns in direct read/list helpers - fails closed for sandbox execution until platform backends enforce glob patterns in #18096 - preserves split filesystem policy in turn context only when it cannot be reconstructed from legacy sandbox policy ## Stack 1. This PR - glob deny-read policy/config/direct-tool support 2. #18096 - macOS and Linux sandbox enforcement 3. #17740 - managed deny-read requirements ## Verification - just fmt - cargo check -p codex-core -p codex-sandboxing --tests --------- Co-authored-by: Codex <noreply@openai.com>github.com-openai-codex · 6862b9c7 · 2026-04-16
- 1.1ETVfix: fix stale proxy env restoration after shell snapshots (#17271) ## Summary This fixes a stale-environment path in shell snapshot restoration. A sandboxed command can source a shell snapshot that was captured while an older proxy process was running. If that proxy has died and come back on a different port, the snapshot can otherwise put old proxy values back into the command environment, which is how tools like `pip` end up talking to a dead proxy. The wrapper now captures the live process environment before sourcing the snapshot and then restores or clears every proxy env var from the proxy crate's canonical list. That makes proxy state after shell snapshot restoration match the current command environment, rather than whatever proxy values happened to be present in the snapshot. On macOS, the Codex-generated `GIT_SSH_COMMAND` is refreshed when the SOCKS listener changes, while custom SSH wrappers are still left alone. --------- Co-authored-by: Codex <noreply@openai.com>github.com-openai-codex · 33fa9524 · 2026-04-20
- 1.1ETVfeat: add websocket auth for app-server (#14847) ## Summary This change adds websocket authentication at the app-server transport boundary and enforces it before JSON-RPC `initialize`, so authenticated deployments reject unauthenticated clients during the websocket handshake rather than after a connection has already been admitted. During rollout, websocket auth is opt-in for non-loopback listeners so we do not break existing remote clients. If `--ws-auth ...` is configured, the server enforces auth during websocket upgrade. If auth is not configured, non-loopback listeners still start, but app-server logs a warning and the startup banner calls out that auth should be configured before real remote use. The server supports two auth modes: a file-backed capability token, and a standard HMAC-signed JWT/JWS bearer token verified with the `jsonwebtoken` crate, with optional issuer, audience, and clock-skew validation. Capability tokens are normalized, hashed, and compared in constant time. Short shared secrets for signed bearer tokens are rejected at startup. Requests carrying an `Origin` header are rejected with `403` by transport middleware, and authenticated clients present credentials as `Authorization: Bearer <token>` during websocket upgrade. ## Validation - `cargo test -p codex-app-server transport::auth` - `cargo test -p codex-cli app_server_` - `cargo clippy -p codex-app-server --all-targets -- -D warnings` - `just bazel-lock-check` Note: in the broad `cargo test -p codex-app-server connection_handling_websocket` run, the touched websocket auth cases passed, but unrelated Unix shutdown tests failed with a timeout in this environment. --------- Co-authored-by: Eric Traut <etraut@openai.com>github.com-openai-codex · 61245642 · 2026-03-25
- 1.0ETVfeat(permissions): resolve permission profile inheritance (#22270) ## Stack This is the foundation PR for the permission-profile inheritance stack. - This PR adds config-level `extends` resolution and merge semantics. - Follow-up: #23705 applies resolved profiles at runtime and updates the active-profile protocol surfaces. ## Why Permission profiles are starting to carry enough policy that copy-pasting near-identical definitions becomes hard to review and easy to drift. Before the runtime can consume inherited profiles, the config layer needs one explicit resolver that can merge parent chains and reject unsafe or invalid inheritance shapes. ## What changed - Add `extends` to permission-profile TOML and resolve parent chains in inheritance order. - Merge inherited profile TOML with the existing config merge behavior while preserving the permission-specific normalization needed for network domain keys. - Keep parent descriptions out of resolved child profiles and record inherited profile names separately for downstream consumers. - Reject undefined parents, unsupported built-in parents, and inheritance cycles with targeted errors. - Cover resolver behavior with TOML fixture tests and refresh the generated config schema. ## Validation - `cargo test -p codex-config` - `cargo test -p codex-core permissions_profiles_`github.com-openai-codex · fe7c069f · 2026-05-20
- 0.8ETV[codex] Bypass managed network for escalated exec (#19595) ## Why `sandbox_permissions = "require_escalated"` is treated as an explicit request to approve the command and run it outside the filesystem/platform sandbox. Before this change, shell and unified exec still registered managed network approval context and could inject Codex-managed proxy state into the child process, which meant an approved escalated command could still hit a second network approval path. This PR makes that escalation boundary consistent: once a command is explicitly approved to run outside the sandbox, Codex does not also route that process through the managed network proxy. ## Security impact Command/filesystem sandbox approval now implies network approval for that command. If an untrusted command or script is allowed to run with `require_escalated`, its network calls are unsandboxed: Codex-managed network allowlists and denylists are not respected for that process, so the command can exfiltrate any data it can read. ## What changed - Skip managed network approval specs for `SandboxPermissions::RequireEscalated`. - Pass `network: None` into shell, zsh-fork shell, and unified exec sandbox preparation for explicitly escalated requests. - Strip Codex-managed proxy environment variables when `CODEX_NETWORK_PROXY_ACTIVE` is present, while preserving user proxy env when the Codex marker is absent. - Add regression coverage for the prepared exec request so the old behavior cannot silently reappear. ## Verification - `cargo test -p codex-core explicit_escalation` - `cargo clippy -p codex-core --all-targets -- -D warnings`github.com-openai-codex · 9aaa5d93 · 2026-04-25
- 0.8ETVfix: support split carveouts in windows elevated sandbox (#14568) ## Summary - preserve legacy Windows elevated sandbox behavior for existing policies - add elevated-only support for split filesystem policies that can be represented as readable-root overrides, writable-root overrides, and extra deny-write carveouts - resolve those elevated filesystem overrides during sandbox transform and thread them through setup and policy refresh - keep failing closed for explicit unreadable (`none`) carveouts and reopened writable descendants under read-only carveouts - for explicit read-only-under-writable-root carveouts, materialize missing carveout directories during elevated setup before applying the deny-write ACL - document the elevated vs restricted-token support split in the core README ## Example Given a split filesystem policy like: ```toml ":root" = "read" ":cwd" = "write" "./docs" = "read" "C:/scratch" = "write" ``` the elevated backend now provisions the readable-root overrides, writable-root overrides, and extra deny-write carveouts during setup and refresh instead of collapsing back to the legacy workspace-only shape. If a read-only carveout under a writable root is missing at setup time, elevated setup creates that carveout as an empty directory before applying its deny-write ACE; otherwise the sandboxed command could create it later and bypass the carveout. This is only for explicit policy carveouts. Best-effort workspace protections like `.codex/` and `.agents/` still skip missing directories. A policy like: ```toml "/workspace" = "write" "/workspace/docs" = "read" "/workspace/docs/tmp" = "write" ``` still fails closed, because the elevated backend does not reopen writable descendants under read-only carveouts yet. --------- Co-authored-by: Codex <noreply@openai.com>github.com-openai-codex · b976e701 · 2026-04-10
- 0.8ETVfix(linux-sandbox): preserve shell cleanup on interruption (#22729) ## Why Interrupted `shell_command` calls can race with the outer tool-dispatch cancellation path. When that happens, the runtime future may be dropped before the spawned process gets a chance to run `SIGTERM` cleanup. For bwrapd-backed Linux sandbox commands, that can leave synthetic protected-path mount bookkeeping such as `.git/.codex` registrations under `/tmp` behind after a TUI interruption. The relevant cancellation points are the outer dispatch race in [`core/src/tools/parallel.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/tools/parallel.rs#L91-L132) and the process shutdown logic in [`core/src/exec.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/exec.rs#L1367-L1393). ## What changed - Keep `shell_command` dispatch alive long enough for the runtime to finish cancellation cleanup instead of immediately returning the synthetic aborted response. - Fold shell-turn cancellation into the existing `ExecExpiration` path in [`core/src/tools/runtimes/shell.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/tools/runtimes/shell.rs#L267-L274), so cancellation and timeout behavior stay centralized. - On cancellation, send `SIGTERM` first, wait briefly for cleanup to run, then hard-kill any remaining descendants in the original process group. - Treat `ESRCH` as an already-gone process-group cleanup case in `codex-utils-pty`, which keeps best-effort teardown from surfacing a stale-process race as an error. ## Verification - `cargo test -p codex-core cancellation` - Added regression coverage for: - `shell_tool_cancellation_waits_for_runtime_cleanup` - `process_exec_tool_call_cancellation_allows_sigterm_cleanup`github.com-openai-codex · 9152ebd2 · 2026-05-27
- 0.7ETVfix: preserve split filesystem semantics in linux sandbox (#14173) ## Stack fix: fail closed for unsupported split windows sandboxing #14172 -> fix: preserve split filesystem semantics in linux sandbox #14173 fix: align core approvals with split sandbox policies #14171 refactor: centralize filesystem permissions precedence #14174 ## Summary ## Summary - Preserve Linux split filesystem carveouts in bubblewrap by applying mount masks in the right order, so narrower rules still win under broader writable roots. - Preserve unreadable ancestors of writable roots by masking them first and then rebinding the narrower writable descendants. - Stop rejecting legacy-plus-split Linux configs that are sandbox-equivalent after `cwd` resolution by comparing semantics instead of raw legacy structs. - Fail closed when callers provide partial split policies, mismatched legacy-plus-split policies, or force `--use-legacy-landlock` for split-only shapes that legacy Landlock cannot enforce. - Add Linux regressions for overlapping writable, read-only, and denied paths, and document the supported split-policy enforcement path. ## Example Given a split filesystem policy like: ```toml [permissions.dev.filesystem] ":root" = "read" "/code" = "write" "/code/.git" = "read" "/code/secrets" = "none" "/code/secrets/tmp" = "write" ``` this PR makes Linux enforce the intended result under bubblewrap: - `/code` stays writable - `/code/.git` stays read-only - `/code/secrets` stays denied - `/code/secrets/tmp` can still be reopened as writable if explicitly allowed Before this, Linux could lose one of those carveouts depending on mount order or legacy-policy fallback. This PR keeps the split-policy semantics intact and rejects configurations that legacy Landlock cannot represent safely.github.com-openai-codex · 774965f1 · 2026-03-12
- 0.7ETVfeat(config): support managed deny-read requirements (#17740) ## Summary - adds managed requirements support for deny-read filesystem entries - constrains config layers so managed deny-read requirements cannot be widened by user-controlled config - surfaces managed deny-read requirements through debug/config plumbing This PR lets managed requirements inject deny-read filesystem constraints into the effective filesystem sandbox policy. User-controlled config can still choose the surrounding permission profile, but it cannot remove or weaken the managed deny-read entries. ## Managed deny-read shape A managed requirements file can declare exact paths and glob patterns under `[permissions.filesystem]`: ```toml # /etc/codex/requirements.toml [permissions.filesystem] deny_read = [ "/Users/alice/.gitconfig", "/Users/alice/.ssh", "./managed-private/**/*.env", ] ``` Those entries are compiled into the effective filesystem policy as `access = none` rules, equivalent in shape to filesystem permission entries like: ```toml [permissions.workspace.filesystem] "/Users/alice/.gitconfig" = "none" "/Users/alice/.ssh" = "none" "/absolute/path/to/managed-private/**/*.env" = "none" ``` The important difference is that the managed entries come from requirements, so lower-precedence user config cannot remove them or make those paths readable again. Relative managed `deny_read` entries are resolved relative to the directory containing the managed requirements file. Glob entries keep their glob suffix after the non-glob prefix is normalized. ## Runtime behavior - Managed `deny_read` entries are appended to the effective `FileSystemSandboxPolicy` after the selected permission profile is resolved. - Exact paths become `FileSystemPath::Path { access: None }`; glob patterns become `FileSystemPath::GlobPattern { access: None }`. - When managed deny-read entries are present, `sandbox_mode` is constrained to `read-only` or `workspace-write`; `danger-full-access` and `external-sandbox` cannot silently bypass the managed read-deny policy. - On Windows, the managed deny-read policy is enforced for direct file tools, but shell subprocess reads are not sandboxed yet, so startup emits a warning for that platform. - `/debug-config` shows the effective managed requirement as `permissions.filesystem.deny_read` with its source. ## Stack 1. #15979 - glob deny-read policy/config/direct-tool support 2. #18096 - macOS and Linux sandbox enforcement 3. This PR - managed deny-read requirements --------- Co-authored-by: Codex <noreply@openai.com>github.com-openai-codex · dae0608c · 2026-04-17
- 0.6ETVfeat(connectors): support managed app tool approval requirements (#21061) ## Why Managed requirements can already centrally disable apps, but they could not express the per-tool app approval rules that normal config already supports. That left admins without a way to enforce connector tool approvals through `/etc/codex/requirements.toml` or cloud requirements. ## What changed - Extend app requirements with per-tool `approval_mode` entries. - Merge managed app tool requirements across managed sources while preserving higher-precedence exact tool settings. - Apply managed tool approvals separately from user app config so managed policy is matched only on raw MCP `tool.name`, while user config keeps the existing raw-name-then-title convenience fallback. - Add coverage for local requirements, cloud requirements parsing, managed-over-user precedence, and a title-collision case that must not widen managed auto-approval. ## Configuration shape Local `/etc/codex/requirements.toml` and cloud requirements use the same TOML shape: ```toml [apps.connector_123123.tools."calendar/list_events"] approval_mode = "approve" ``` This is a per-tool approval rule keyed by app ID and raw MCP tool name, not an app-level boolean such as `apps.connector_123123.approve = true`.github.com-openai-codex · d0fa2d81 · 2026-05-11
- 0.6ETVfix: keep permissions profiles forward compatible (#14107) ## Summary - preserve unknown `:special_path` tokens, including nested entries, so older Codex builds warn and ignore instead of failing config load - fail closed with a startup warning when a permissions profile has missing or empty filesystem entries instead of aborting profile compilation - normalize Windows verbatim paths like `\?\C:\...` before absolute-path validation while keeping explicit errors for truly invalid paths ## Testing - just fmt - cargo test -p codex-core permissions_profiles_allow - cargo test -p codex-core normalize_absolute_path_for_platform_simplifies_windows_verbatim_paths - cargo test -p codex-protocol unknown_special_paths_are_ignored_by_legacy_bridge - cargo clippy -p codex-core -p codex-protocol --all-targets -- -D warnings - cargo cleangithub.com-openai-codex · 1165a16e · 2026-03-10