Skip to content

Re-emit denyRead paths nested under allowRead on macOS#311

Merged
shawnm-anthropic merged 1 commit into
mainfrom
fix/macos-allow-read-ancestor-unmasks-deny
Jun 15, 2026
Merged

Re-emit denyRead paths nested under allowRead on macOS#311
shawnm-anthropic merged 1 commit into
mainfrom
fix/macos-allow-read-ancestor-unmasks-deny

Conversation

@poteat

@poteat poteat commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

TLDR: a denyRead path nested under allowRead was being re-allowed by the broader rule; re-emit the deny last.

Seatbelt is last-match-wins, and generateReadRules emits deny then allow. Re-emit any literal denyOnly path that sits inside a literal allowWithinDeny subpath so the more-specific deny lands last. Glob denies are out of scope (regex-vs-subpath nesting isn't decidable here); denyReadAlways (#284) remains the lever for that.

Test Plan

New allow-read.test.ts case asserts the /work/secrets deny appears both before and after the /work allow in the emitted profile.

Links

Seatbelt is last-match-wins, so a literal denyRead path that sits inside
a literal allowRead subpath was being re-allowed by the broader rule
emitted after it. Re-emit the deny last so the more-specific rule wins.
Glob denies are out of scope (regex-vs-subpath nesting isn't decidable
here); denyReadAlways remains the explicit lever for that case.
@shawnm-anthropic shawnm-anthropic merged commit 16589a8 into main Jun 15, 2026
8 checks passed
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.

2 participants