fix(seatbelt): widen per-user Darwin temp grant to its container#659
Open
caarlos0 wants to merge 5 commits into
Open
fix(seatbelt): widen per-user Darwin temp grant to its container#659caarlos0 wants to merge 5 commits into
caarlos0 wants to merge 5 commits into
Conversation
On macOS `$TMPDIR` is the per-user `_CS_DARWIN_USER_TEMP_DIR` (`/var/folders/<a>/<b>/T/`); its siblings `C` (`_CS_DARWIN_USER_CACHE_DIR`) and `0` (misc) share the same per-user container but were left unwritable when only the temp leaf was granted, so sandboxed tools that stage under the per-user cache were denied. Widen a read-write grant on a `T`/`C`/`0` leaf to its enclosing `/var/folders/<a>/<b>` container in the Seatbelt profile builder, so all three siblings are covered by one grant. The guard is strict — only a direct `T`/`C`/`0` child of a genuine two-segment per-user container (optionally under `/private`, the post-canonicalization form) qualifies, so a grant can never widen up to `/var/folders` (every user) or `/`. `deniedPaths` still override, since denies are emitted after allows (last-match-wins). Applied unconditionally in the platform-agnostic profile builder because a Seatbelt profile is always a macOS artifact regardless of build host, matching the existing `guiAccess` `/private/var/folders` grant. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4e17ae47-34f1-4c15-8f22-8eb86f7b12a5 Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adjusts the macOS Seatbelt profile generator to broaden certain readwritePaths entries that target per-user Darwin temp/cache leaves under /var/folders/<a>/<b>/{T,C,0} so the enclosing per-user container is granted instead, preventing cache-related write denials in sandboxed tools. The change is implemented in the profile builder so it benefits all macOS backend consumers (CLI/SDKs/FFI) without duplicating Darwin path knowledge.
Changes:
- Widen
readwritePathsgrants for/var/folders/<a>/<b>/{T,C,0}(and/private/...) to/var/folders/<a>/<b>in the Seatbelt profile builder. - Add unit tests validating widening behavior and non-matching cases.
- Document the widening behavior in the Seatbelt backend docs.
Show a summary per file
| File | Description |
|---|---|
| src/backends/seatbelt/common/src/profile_builder.rs | Adds Darwin temp/cache leaf widening logic in write_filesystem_allow plus new helper + tests. |
| docs/macos-support/seatbelt-backend.md | Documents the readwritePaths widening behavior and its safety constraints. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Low
darwin_temp_container_grant accepted any non-empty <a>/<b> segment, so a path-traversal input like /var/folders/ab/../T widened to /var/folders/ab/.. (effectively /var/folders), over-broadening the grant and contradicting the documented "never widen up to /var/folders or /" guarantee. Genuine Darwin per-user container segments are never . or .., so reject those (and empty) segments before widening, and cover the traversal cases in the rejection test. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4e17ae47-34f1-4c15-8f22-8eb86f7b12a5 Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
Express the .-/..-rejection with matches!(*s, "." | ".."), matching the leaf check in the same function. Behavior-preserving. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4e17ae47-34f1-4c15-8f22-8eb86f7b12a5 Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
huzaifa-d
reviewed
Jul 20, 2026
huzaifa-d
reviewed
Jul 20, 2026
Addresses review feedback: widening a per-user Darwin temp/cache leaf grant to the whole '/var/folders/<a>/<b>' container made every directory under it writable, not just the T/C/0 siblings, so callers lost least-privilege access to other subdirs. Expand instead to exactly the three well-known siblings (.../T, .../C, .../0) and never grant the container itself. Also add the requested test: granting the T leaf allows the C sibling, and a deniedPaths entry on C still wins via last-match ordering (allow-then-deny). Rename darwin_temp_container_grant -> darwin_temp_sibling_grants (now returns the three sibling paths) and update the backend doc. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 4e17ae47-34f1-4c15-8f22-8eb86f7b12a5 Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
Contributor
Author
|
@huzaifa-d thank you, resolved. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📖 Description
On macOS,
$TMPDIRis the per-user_CS_DARWIN_USER_TEMP_DIR(/var/folders/<a>/<b>/T/). Its siblings under the same per-user container —C(_CS_DARWIN_USER_CACHE_DIR) and0(misc) — are left unwritable when a sandbox is granted read-write access to only the temp leaf, so tools that stage under the per-user cache get denied.This expands a read-write grant that targets a per-user Darwin temp/cache leaf into read-write grants for its three well-known per-user siblings (
.../T,.../C,.../0) in the Seatbelt profile builder (write_filesystem_allow). Because the expansion lives in the profile builder, it applies to every consumer of the macOS backend (CLI, Node SDK, C#/FFI, Rust SDK) — none of them has to carry macOS/var/folderspath knowledge.The expansion is strictly guarded by a new
darwin_temp_sibling_grantshelper:/var/folders/<a>/<b>/<leaf>with<leaf>one ofT,C, or0(optionally under/private, the post-canonicalization form) and<a>/<b>are ordinary segments (never empty,., or..)./var/folders/<a>/<b>container itself, so no other directory under the container becomes writable and a caller keeps least-privilege access to everything outside theT/C/0triad../..traversal segment, or anything outside/var/foldersyields no expansion — so an expansion can never reach the container root,/var/folders(every user's containers), or/.deniedPathsstill override the expanded grants, since denies are emitted after allows (Seatbelt last-match-wins), so a caller can carve any single sibling back out.guiAccess/private/var/foldersgrant.The change only adds sibling grants;
$TMPDIR(=.../T) itself was already granted, so no previously-working sandboxed command can break.🔗 References
No linked issue. The macOS backend filesystem behavior is documented in
docs/macos-support/seatbelt-backend.md, updated in this PR.🔍 Validation
All on a macOS host (
aarch64-apple-darwin), run fromsrc/:cargo test -p seatbelt_common— 49 passed, incl. tests for the sibling expansion, non-per-user rejection (including./..traversal), a profile-integration test asserting all three siblings are granted while the bare container is not, and a deny-after-allow test proving adeniedPathsentry on a sibling still wins.cargo fmt -p seatbelt_common -- --check— clean.cargo clippy -p seatbelt_common --all-targets -- -D warnings— clean.✅ Checklist
Cargo.lock, thedependency-feed-checkcheck passes (no dependency change)📋 Issue Type
Microsoft Reviewers: Open in CodeFlow