codex - 💡(How to fix) Fix macOS permission profiles cannot re-allow child paths under a denied parent path [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openai/codex#21081Fetched 2026-05-05 05:53:43
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
0
Participants
Timeline (top)
labeled ×4

Error Message

  • add a second explicit allow file-read* block for more-specific child exception roots;
  1. Update ReadDenyMatcher so exact path denies use the same most-specific precedence as resolve_access_with_cwd, instead of treating deny roots as unconditional prefix masks. Deny globs can stay hard-deny unless glob exception semantics are added separately.

Code Example

[permissions.locked.filesystem]
":project_roots" = { "." = "write" }
"/tmp" = "write"
"/private/tmp" = "write"
"/private/var/folders" = "write"

"/Users/me" = "none"
"/Users/me/.gitconfig" = "read"
"/Users/me/.cache/uv" = "write"

---

ls ~                                      fails
ls ~/.gitconfig >/dev/null                succeeds
ls ~/.cache/uv >/dev/null                 succeeds
wc -c < ~/.config/my-app/.env >/dev/null  fails

---

approval_policy = "never"
sandbox_mode = "workspace-write"
default_permissions = "locked"

[permissions.locked.filesystem]
":project_roots" = { "." = "write" }
"/tmp" = "write"
"/private/tmp" = "write"
"/private/var/folders" = "write"
"/etc/ssl" = "read"
"/System/Library/OpenSSL" = "read"
"/Library/Developer/CommandLineTools" = "read"

"/Users/me" = "none"
"/Users/me/.gitconfig" = "read"
"/Users/me/.cache/uv" = "write"

[permissions.locked.network]
enabled = true
mode = "full"

---

codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'ls ~ >/dev/null'
codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'ls ~/.gitconfig >/dev/null'
codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'ls ~/.cache/uv >/dev/null'
codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'wc -c < ~/.config/my-app/.env >/dev/null 2>&1'

---

ls ~                                      fails
ls ~/.gitconfig >/dev/null                succeeds
ls ~/.cache/uv >/dev/null                 succeeds
wc -c < ~/.config/my-app/.env >/dev/null  fails
RAW_BUFFERClick to expand / collapse

What version of the Codex App are you using (From “About Codex” dialog)?

Version 26.429.30905 (2345)

What subscription do you have?

Pro

What platform is your computer?

Darwin 24.6.0 arm64 arm

What issue are you seeing?

On macOS, permission profiles appear unable to preserve most-specific filesystem precedence when a parent path is denied and a child path is explicitly allowed.

Example desired policy:

[permissions.locked.filesystem]
":project_roots" = { "." = "write" }
"/tmp" = "write"
"/private/tmp" = "write"
"/private/var/folders" = "write"

"/Users/me" = "none"
"/Users/me/.gitconfig" = "read"
"/Users/me/.cache/uv" = "write"

Desired behavior:

ls ~                                      fails
ls ~/.gitconfig >/dev/null                succeeds
ls ~/.cache/uv >/dev/null                 succeeds
wc -c < ~/.config/my-app/.env >/dev/null  fails

Observed behavior: the broad home deny also blocks the nested allow entries.

This looks like a macOS Seatbelt projection issue. Codex’s permission resolver appears to support most-specific path precedence, but the generated Seatbelt policy seems to turn exact deny roots into broad carveouts that shadow more-specific child allow rules.

What steps can reproduce the bug?

Use a profile like this, replacing /Users/me as needed:

approval_policy = "never"
sandbox_mode = "workspace-write"
default_permissions = "locked"

[permissions.locked.filesystem]
":project_roots" = { "." = "write" }
"/tmp" = "write"
"/private/tmp" = "write"
"/private/var/folders" = "write"
"/etc/ssl" = "read"
"/System/Library/OpenSSL" = "read"
"/Library/Developer/CommandLineTools" = "read"

"/Users/me" = "none"
"/Users/me/.gitconfig" = "read"
"/Users/me/.cache/uv" = "write"

[permissions.locked.network]
enabled = true
mode = "full"

Then run:

codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'ls ~ >/dev/null'
codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'ls ~/.gitconfig >/dev/null'
codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'ls ~/.cache/uv >/dev/null'
codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'wc -c < ~/.config/my-app/.env >/dev/null 2>&1'

What is the expected behavior?

Most-specific path rules should win consistently in the macOS runtime sandbox.

Expected result:

ls ~                                      fails
ls ~/.gitconfig >/dev/null                succeeds
ls ~/.cache/uv >/dev/null                 succeeds
wc -c < ~/.config/my-app/.env >/dev/null  fails

Additional information

Possible fix without new config syntax:

  1. In codex-rs/protocol/src/permissions.rs, expose readable roots that are more-specific descendants of unreadable roots, for example get_readable_roots_under_unreadable_roots_with_cwd(...).

  2. In codex-rs/sandboxing/src/seatbelt.rs, when generating the read policy:

    • keep the existing broad allow with denied roots carved out;
    • add a second explicit allow file-read* block for more-specific child exception roots;
    • add metadata-only traversal for denied ancestors so the child path can be reached without enabling ls ~.
  3. Update ReadDenyMatcher so exact path denies use the same most-specific precedence as resolve_access_with_cwd, instead of treating deny roots as unconditional prefix masks. Deny globs can stay hard-deny unless glob exception semantics are added separately.

Related: #2847, but this issue is narrower: it is specifically about parent-deny / child-allow behavior in macOS permission-profile enforcement.

extent analysis

TL;DR

The issue can be fixed by modifying the codex-rs code to correctly handle most-specific path precedence when a parent path is denied and a child path is explicitly allowed.

Guidance

  • Review the suggested changes in the codex-rs/protocol/src/permissions.rs and codex-rs/sandboxing/src/seatbelt.rs files to expose readable roots under unreadable roots and generate the correct read policy.
  • Update the ReadDenyMatcher to use most-specific precedence for exact path denies, instead of treating deny roots as unconditional prefix masks.
  • Test the changes using the provided example policy and commands to verify the correct behavior.

Example

No code snippet is provided as the issue suggests modifying existing code, but the example policy and commands can be used to test the changes:

codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'ls ~ >/dev/null'
codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'ls ~/.gitconfig >/dev/null'
codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'ls ~/.cache/uv >/dev/null'
codex sandbox macos --permissions-profile locked -- /bin/zsh -lc 'wc -c < ~/.config/my-app/.env >/dev/null 2>&1'

Notes

The issue is specific to macOS permission-profile enforcement and requires changes to the codex-rs code. The suggested changes aim to fix the issue without introducing new config syntax.

Recommendation

Apply the suggested changes to the codex-rs code to fix the issue, as they provide a clear and targeted solution to the problem.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix macOS permission profiles cannot re-allow child paths under a denied parent path [1 participants]