Skip to content

fix: preserve reopened descendants under read denies#21311

Open
viyatb-oai wants to merge 2 commits intomainfrom
codex/viyatb/fix-seatbelt-reopened-children
Open

fix: preserve reopened descendants under read denies#21311
viyatb-oai wants to merge 2 commits intomainfrom
codex/viyatb/fix-seatbelt-reopened-children

Conversation

@viyatb-oai
Copy link
Copy Markdown
Collaborator

@viyatb-oai viyatb-oai commented May 6, 2026

Why

FileSystemSandboxPolicy already resolves exact-path conflicts by choosing the most-specific matching entry (resolve_access_with_cwd). For example, this profile is meant to deny a broader subtree while reopening a couple of specific descendants:

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

Before this change, the projected macOS policy still could not reach the reopened descendants because traversing /Users/me itself was denied. In that example, reading /Users/me/.gitconfig and writing under /Users/me/.cache/uv could fail even though the narrower entries were supposed to win.

After this change, the reopened descendants work while the broader deny still holds:

  • reading /Users/me/.gitconfig works
  • writing under /Users/me/.cache/uv works
  • listing /Users/me still fails
  • unrelated children such as /Users/me/.ssh/config stay denied unless they are explicitly reopened

Fixes #21081.

What changed

  • Make ReadDenyMatcher preserve exact-path precedence instead of treating every denied exact root as an unconditional subtree mask.
  • When generating the macOS policy, add exact file-read-metadata grants only for unreadable ancestor directories that are necessary to reach explicitly reopened readable or writable descendants.
  • Add regression coverage for both the rendered policy and real macOS execution behavior: the denied parent stays blocked, the reopened child works, unrelated siblings stay blocked, and a reopened writable child can still be written.

Verification

  • cargo test -p codex-protocol
  • cargo test -p codex-sandboxing

Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e01fd53004

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

.into_iter()
.map(|path| normalized_and_canonical_candidates(path.as_path()))
.flat_map(|entry| {
normalized_and_canonical_candidates(entry.path.as_path())
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Do not canonicalize allow entries for deny matching

ReadDenyMatcher now canonicalizes every exact entry, including read/write allows. If /real is denied and /alias/child is allowed where /alias symlinks to /real, is_read_denied('/real/child/file') becomes false because the allow is stored as /real/child. resolve_access_with_cwd would still deny that canonical path, so direct read-deny checks can bypass an exact deny via a symlinked allow.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in caf7dda. ReadDenyMatcher now resolves lexical exact entries first and only falls back to canonicalized deny entries when no lexical entry matched, so an alias-specific allow cannot reopen the canonical denied target. I also added symlinked_allow_alias_does_not_reopen_canonical_denied_path to cover this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

macOS permission profiles cannot re-allow child paths under a denied parent path

1 participant