Permission profiles cannot protect absent nested metadata paths across Seatbelt and bubblewrap
What version of Codex CLI is running?
- macOS reproduction:
codex-cli 0.149.0 - Linux/WSL reproduction:
codex-cli 0.149.1
What platforms are affected?
- macOS 26.0 arm64 using Seatbelt
- Windows 11 ARM64 WSL2, Ubuntu aarch64, using bubblewrap
What issue are you seeing?
Custom filesystem permission profiles do not have a portable way to protect an exact nested path that does not exist when the sandbox is constructed while leaving its existing parent writable.
The affected Git metadata family includes absent commondir, config.worktree, and .lfsconfig files plus absent hooks and modules directories. These targets can redirect Git topology, per-worktree configuration, Git LFS traffic, hook execution, or submodule metadata after creation. Making all of .git and the worktree root read-only would prevent normal agent Git workflows.
On macOS, an exact read rule for an absent .git/commondir does not reserve the path. A command inside codex sandbox can create the file successfully. A post-session topology verifier detects the change, but the sandbox itself does not prevent it.
Observed macOS receipt:
margay_codex_version=codex-cli 0.149.0
preflight_manifest=pass
sandbox_status=0
absent_commondir_creation=allowed_by_seatbelt
postflight_manifest_status=1
codex-git-topology: topology verification failed
poison_evidence_preserved=yes
restored_manifest=pass
On Linux/WSL, adding exact protection for an absent nested metadata path can instead make bubblewrap fail during sandbox construction, before the requested command runs. The same machine reproduced startup failures for absent .lfsconfig and .git/modules targets:
bwrap: Can't create file at /home/jasen/dev/dotfiles/.zsh/zsh-autosuggestions/.lfsconfig: Read-only file system
bwrap: Can't create file at /home/jasen/dev/dotfiles/.zsh/zsh-autosuggestions/.git/modules: Read-only file system
Removing those collision-prone exact rules restores startup, but recursive deny fallbacks do not reserve the absent targets. Exact-head acceptance on codex-cli 0.149.1 observed:
root_a_startup=pass
root_b_startup=pass
config_write=denied
hooks_create=ALLOWED
modules_create=ALLOWED
config_worktree_create=ALLOWED
lfsconfig_create=ALLOWED
absent_commondir_creation=allowed_by_bwrap
postflight_manifest_status=1
codex-git-topology: topology verification failed
poison_evidence_preserved=yes
restored_manifest=pass
Related missing-path and nested-repository behavior is already tracked in:
- #40433
- #37081
This report focuses on the missing conditional primitive exposed by the cross-backend difference: protect this exact path if it appears, without requiring it to exist at sandbox construction and without making its writable parent read-only.
Minimal policy shape
[permissions.example.filesystem.":workspace_roots"]
"." = "write"
".git/commondir" = "read"
The repository begins with an existing .git directory and no .git/commondir. Equivalent behavior is needed for the other absent metadata targets named above.
Expected behavior
Codex should be able to express an exact path reservation or equivalent conditional policy:
- sandbox startup succeeds when the protected nested path is absent;
- the existing parent remains writable;
- creating or replacing the protected path inside the sandbox is denied;
- behavior is consistent across Seatbelt and bubblewrap.
Actual behavior
- Seatbelt starts successfully but allows the absent path to be created.
- Bubblewrap may try to materialize or mask the absent target and fail sandbox startup.
- Recursive deny patterns do not reliably prevent creation of the absent target.
Current application-level containment
Our launcher records every absent-or-existing protected target, verifies topology before trusted launch and after session exit, preserves evidence on drift, and prevents the trusted push wrapper from operating on changed topology. Existing targets receive exact read-only rules. This closes trusted relaunch and push paths but cannot prevent a raw Git or Git LFS client invoked after in-session absent-target creation and before post-session verification.
1 Comment
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action