openai / openai/codex

Execpolicy allow rules silently stay sandboxed when any denied-read path is configured

Open
#38,318 3 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app bug sandbox
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 whenever has_denied_read_restrictions() is true.
  • sandbox_override_for_first_attempt() therefore refuses BypassSandboxFirstAttempt even for Skip { bypass_sandbox: true }.
  • Unix rule escalation maps a policy-driven match to EscalationExecution::TurnDefault when unsandboxed execution is not allowed.

Sources:

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:

  1. 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
  2. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.