Skip to content

macOS: pin mandatory-deny directories at any depth - #484

Open
ant-kurt wants to merge 3 commits into
mainfrom
fix/nested-git-dir-pin
Open

macOS: pin mandatory-deny directories at any depth#484
ant-kurt wants to merge 3 commits into
mainfrom
fix/nested-git-dir-pin

Conversation

@ant-kurt

@ant-kurt ant-kurt commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

The move-blocking rules only pinned the literal <cwd>/.git, so a nested .git could be created, renamed onto, or renamed away at any depth. Every glob-shaped ancestor of a deny glob (**/.git, **/.claude, …) is now denied file-write-create/file-write-unlink, exact match. Writes inside an existing nested .git still work; creating or removing a nested .git inside the sandbox (git init, clone, worktree add, rm -rf of a nested repo) is now denied. The README's mandatory-deny section states this and summarizes macOS vs Linux coverage.

Test plan

macos-seatbelt.test.ts "Nested .git Swap Prevention": rename of a prepared directory onto a nested .git, mkdir/symlink of a nested .git, and renaming an existing nested .git away are denied; index.lock → index and refs/ writes inside an existing nested .git succeed. Existing suite unchanged.

…ory denies on Windows

macOS: generateMoveBlockingRules derived rename protection from a deny
glob's static prefix, so for the cwd-anchored `**/.git/config` and
`**/.git/hooks/**` globs only the literal `<cwd>/.git` was pinned. A
sandboxed command could prepare a directory holding a config with
core.fsmonitor and rename it onto `packages/app/.git` (or mkdir / symlink
it); Seatbelt checks the rename target, not the children carried with it.
Every glob-shaped ancestor (`**/.git`, `**/.claude`, ...) is now denied
file-write-create / file-write-unlink at any depth, exact match, so writes
inside an existing nested .git keep working. Creating or removing a
nested .git (git init, clone, worktree add, rm -rf of a nested repo)
inside the sandbox is now denied.

Windows: the ACL stamp only covered the caller's own denyWrite. The
mandatory set (.git/hooks, .git/config, shell rc files, IDE dirs) is now
expanded to existing paths under cwd, bounded by mandatoryDenySearchDepth
via a new expandGlobPattern maxDepth option, and unioned into denyWrite.

Linux is unchanged: bubblewrap can only mask paths that exist at command
start (documented limitation).
@ant-kurt ant-kurt changed the title Pin mandatory-deny directories at any depth; add Windows mandatory denies Pin mandatory-deny directories at any depth on macOS; add Windows mandatory denies Aug 21, 2026
@ant-kurt ant-kurt changed the title Pin mandatory-deny directories at any depth on macOS; add Windows mandatory denies macOS: pin mandatory-deny directories at any depth Aug 21, 2026
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.

1 participant