Execpolicy allow rules silently stay sandboxed when any denied-read path is configured
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- PR merge metrics
- PR metrics pending
Description
What variant of Codex are you using?
Codex Desktop on macOS.
What version of Codex is running?
- Desktop:
26.803.81509 - Bundled CLI:
0.147.0-alpha.6.6
What is the issue?
An execpolicy allow rule silently stops running its matching command outside the sandbox as soon as the active filesystem permission profile contains any denied-read restriction.
This conflicts with the Rules documentation, which describes rules as controlling which commands run outside the sandbox. codex execpolicy check still reports allow, but execution remains in the default sandbox and no diagnostic explains that the rule cannot provide the documented sandbox placement.
Minimal reproduction
Use a synthetic denied path so no credential or private path is involved:
approval_policy = "on-request"
default_permissions = "repro"
[permissions.repro.filesystem]
":root" = "write"
"/tmp/codex-denied-read-probe" = "deny"
Add a matching rule:
prefix_rule(
pattern = ["/usr/bin/open"],
decision = "allow",
justification = "Synthetic sandbox-placement probe.",
match = [
"/usr/bin/open -Rb com.apple.TextEdit",
],
)
Verify the policy result:
$ codex execpolicy check --rules <CODEX_HOME>/rules/repro.rules --pretty /usr/bin/open -Rb com.apple.TextEdit
Decision: allow
Run the matching command directly from a Desktop task. It still receives the Seatbelt environment and LaunchServices access fails as it does for an ordinary sandboxed command.
The result is deterministic in the matching release source:
unsandboxed_execution_allowed()returns false wheneverhas_denied_read_restrictions()is true.sandbox_override_for_first_attempt()therefore refusesBypassSandboxFirstAttempteven forSkip { bypass_sandbox: true }.- Unix rule escalation maps a policy-driven match to
EscalationExecution::TurnDefaultwhen unsandboxed execution is not allowed.
Sources:
- https://github.com/openai/codex/blob/rust-v0.147.0-alpha.6.6/codex-rs/core/src/tools/sandboxing.rs
- https://github.com/openai/codex/blob/rust-v0.147.0-alpha.6.6/codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs
- https://learn.chatgpt.com/docs/agent-configuration/rules
Expected behavior
A single denied-read path should not silently disable every configured per-command sandbox escape.
The safety check must not simply be removed: running the current command process unsandboxed would discard the denied-read restrictions. Instead, Codex needs either:
- a trusted host-side command executor that can run an explicitly matched executable outside the agent sandbox while the agent and ordinary shell commands remain subject to denied reads; or
- an independent sandbox-placement policy with a security model that preserves the intended credential boundary.
At minimum, if the active permission model cannot honor an outside-sandbox rule, config validation and runtime output should report that incompatibility instead of returning allow and silently using TurnDefault.
Impact
The current behavior makes two documented safety mechanisms mutually exclusive:
- denied reads protect credentials and other sensitive files from ordinary agent commands;
- Rules are supposed to let selected trusted CLIs use host-only state outside the sandbox.
Configuring even one denied-read path removes the second capability globally. Users must then choose between dropping credential protection, using full access, or implementing a separate trusted broker.
This is a concrete interaction with the broader sandbox-placement/approval separation requested in #20917.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce the configuration with the denied-read path, then read codex-rs/core/src/tools/sandboxing.rs and codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs. Trace unsandboxed_execution_allowed(), sandbox_override_for_first_attempt(), and the TurnDefault mapping. Done means the documented interaction is either safely supported or rejected with a clear diagnostic without discarding denied-read restrictions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, rust
- Domain
- cli, operating-systems, security
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100