macOS app-server: nested workspace-write tools fail before execution with sandbox_apply exit 71
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
Summary
On macOS, a long-running Codex app-server that is already running under an outer Seatbelt policy cannot start normal workspace-write tool commands. Both exec_command and the internal apply_patch tool fail before the requested operation begins with:
sandbox-exec: sandbox_apply: Operation not permitted
The same read-only command succeeds when retried through require_escalated, which bypasses the failing nested sandbox path. This points to sandbox setup rather than project file permissions.
Environment
- macOS 26.6 / Darwin 25.6.0, Apple Silicon arm64
- Bundled Codex CLI: 0.154.0-alpha.6.2
- Surface: long-running codex app-server over stdio
- Parent app-server process is already constrained by an outer macOS Seatbelt policy
- Turn policy: workspace-write
- cwd and writable root both contain the target file
Observed behavior
A normal exec_command that only reads a file inside the writable workspace fails immediately:
sandbox-exec: sandbox_apply: Operation not permitted
No command output is produced, indicating that the requested child command never starts.
Retrying the same read via require_escalated succeeds.
The internal apply_patch tool also fails on a file inside the workspace:
apply_patch verification failed: Failed to read file to update $WORKSPACE/file.md:
fs sandbox helper failed with status exit status: 71:
sandbox-exec: sandbox_apply: Operation not permitted
Because apply_patch has no per-call escalation path, ordinary workspace edits are blocked even though the file is within the declared writable root.
Expected behavior
- A workspace-write tool call should be able to read and edit files inside its declared writable root even when app-server has an outer security boundary.
- If nested Seatbelt application is unsupported, the runtime should preserve the parent sandbox and avoid applying a conflicting child sandbox, or return a structured diagnostic with a safe recovery path.
- apply_patch should not become unusable solely because its sandbox helper cannot apply a second profile.
Reproduction outline
- Launch codex app-server on macOS from a parent process already constrained by Seatbelt.
- Start a turn using workspace-write with a valid cwd and writable root.
- Run a trivial exec_command against a file inside that root.
- Run apply_patch against the same file.
- Observe both fail before execution with sandbox_apply and exit 71.
- Retry the read through require_escalated and observe it succeed.
Notes
This resembles nested macOS sandbox failures reported in:
- #30615
- #26262
- #18243
- #19020
The exact surface here is different: a long-running app-server turn where both exec_command and internal apply_patch fail, while the same command succeeds through the escalation path.
I have not disabled sandboxing as a workaround because that would weaken the intended security boundary.
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
Begin by tracing the macOS sandbox setup used by the app-server's exec_command and apply_patch paths; no source files or tests are identified in the report. Reproduce the nested Seatbelt case and compare normal workspace-write with require_escalated. Done means workspace reads and edits work under an outer policy, or a structured safe diagnostic and recovery path is covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, rust
- Domain
- backend, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100