Resolved linked-worktree Git directory is unreadable with `:root = "deny"`
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- PR merge metrics
- PR metrics pending
Description
What version of Codex CLI is running?
codex-cli 0.147.0
What subscription do you have?
ChatGPT Plus
Which model were you using?
gpt-5.6-sol
What platform is your computer?
Darwin 25.5.0 arm64 arm macOS 26.5.2 on Apple Silicon.
What terminal emulator and version are you using (if applicable)?
Zed using the Codex integration.
Codex doctor report
Not included because the affected session was running through the Zed integration. A redacted CLI doctor report from the same Codex installation can be provided if useful.
What issue are you seeing?
A custom permission profile extends :workspace but denies filesystem reads by default:
default_permissions = "restricted-workspace"
[permissions.restricted-workspace]
extends = ":workspace"
[permissions.restricted-workspace.filesystem]
":minimal" = "read"
":root" = "deny"
When the active workspace is a Git linked worktree, its .git pointer file is readable, but the resolved Git metadata directory outside the workspace is not.
Example layout:
/Users/me/dev/repo/.git/
/Users/me/dev/worktrees/repo/task/
The worktree contains:
gitdir: /Users/me/dev/repo/.git/worktrees/task
Codex can read the worktree's .git file, but the sandbox denies reads from the resolved directory, including:
/Users/me/dev/repo/.git/worktrees/task/HEAD
/Users/me/dev/repo/.git/worktrees/task/commondir
The worktree is listed as an active workspace root by /status.
Explicitly adding the main repository's .git directory as a read permission works around the problem:
[permissions.restricted-workspace.filesystem]
"/Users/me/dev/repo/.git" = "read"
Removing ":root" = "deny" also avoids the problem, but restores broad filesystem read access and defeats the least-privilege purpose of the custom profile.
What steps can reproduce the bug?
- Create a normal Git repository.
- Create a linked worktree in a directory outside the main checkout.
- Configure and select the permission profile shown above.
- Launch Codex with the linked worktree as the workspace.
- Confirm that
/statuslists the linked worktree as a workspace root. - Run:
cat .git
gitdir=$(sed -n 's/^gitdir: //p' .git)
cat "$gitdir/HEAD"
cat "$gitdir/commondir"
git status
The .git pointer can be read, but reads from $gitdir are denied by the sandbox.
What is the expected behavior?
When a workspace root contains a .git pointer file, Codex should dynamically add the resolved worktree Git directory and common Git directory to the readable roots.
These paths should remain protected from writes unless separately authorized.
This would match the documented workspace-write behavior:
If
/.gitis a pointer file (gitdir: ...), the resolved Git directory path is also protected as read-only.
A read-only protected path should remain readable when a custom permission profile replaces ambient root reads with an explicit allowlist.
Additional information
This appears distinct from existing reports about Git metadata being read-only for writes:
- https://github.com/openai/codex/issues/19786
- https://github.com/openai/codex/issues/23661
- https://github.com/openai/codex/issues/24115
Those issues concern operations such as git add and git commit. This report concerns basic read access needed by commands such as git status.
Possible root-cause hypothesis:
In the macOS sandbox implementation, resolved Git metadata appears to be added as a protected path in the write policy. When full-disk reads are disabled, however, the read policy appears to admit only explicitly configured readable roots. The dynamically resolved Git directory does not appear to be added to that set.
Relevant implementation:
https://github.com/openai/codex/blob/rust-v0.147.0/codex-rs/sandboxing/src/seatbelt.rs#L595-L681
A possible fix would be to resolve the active workspace's .git pointer and commondir, add those locations to the sandbox's readable roots, and retain the existing recursive write protection.
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
Read codex-rs/sandboxing/src/seatbelt.rs around lines 595-681, then reproduce the linked-worktree case with the restricted-workspace profile and the commands in the issue. Trace how the .git pointer and commondir are handled for read and write policies; done means git status and reads of HEAD and commondir work while writes remain protected.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, rust
- Domain
- operating-systems, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100