feat(claudecode): emit permission path rules in the forms Claude Code matches, and make sandbox authorable - #2472
Merged
dyoshikawa merged 2 commits intoJul 29, 2026
Conversation
… matches, and make sandbox authorable Claude Code's file permission checks match only Edit(path) and Read(path); a Write/NotebookEdit/Glob rule with a path is never matched and warns at startup, so a canonical write/notebookedit rule with a pattern is now written as Edit(pattern) and a glob rule as Read(pattern). Tool-name rules with no path are unaffected. The claudecode permissions override also gained the sandbox subtree, merged into the top level of settings.json and round-tripped on import.
…e sandbox Review follow-ups: rewriting a write/glob rule to Edit/Read no longer claims those tool names wholesale, which was deleting the ignore feature's Read denies and hand-written Edit rules from settings.json. Ownership is now per emitted entry, which also moves a rewritten entry when its action changes. Sandbox merges recursively so setting a flag under network keeps the denied domains beside it.
This was referenced Jul 29, 2026
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.
Background
Related issue: #2397 (gaps 4 and 6; gaps 1, 2, 3 and 5 landed in #2471)
Two Claude Code permission-surface gaps remained after #2471.
Changes
Warned permission forms (gap 4). The permissions docs state, as of v2.1.210: "The file permission checks match only
Edit(path)andRead(path)rules. AWrite(path),NotebookEdit(path), orGlob(path)rule is accepted but never matched by those checks, so Claude Code warns at startup for each allow, deny, or ask rule in one of these unmatched forms." Rulesync generated exactly those forms, so a canonicalwrite: {"docs/**": "deny"}produced a rule Claude Code warned about and never applied.A canonical
writeornotebookeditrule carrying a pattern is now written asEdit(pattern), and aglobrule asRead(pattern). A rule whose pattern is*is a tool-name rule with no path — the docs say it is unaffected — so it is still written as the bareWrite/NotebookEdit/Glob.The managed-tool set claims the alias only when a category actually has a path rule, and keeps claiming the original name so entries an earlier rulesync wrote in the warned form are replaced rather than left behind. Verified against a settings.json holding the old forms.
Because two categories can now produce one entry, a disagreement between them (
editallowing whatwritedenies) is warned about; both are still written, and Claude Code applies deny first.sandbox.*(gap 6). Theclaudecodepermissions override gained asandboxkey — a loose passthrough on the same terms as the existingpermissionsone — merged into the top level of.claude/settings.jsonand routed back on import. The merge is one level deep, matching thepermissionsprecedent: sibling keys survive, an authored subtree replaces the existing one. #2129 deferred this explicitly; it is a passthrough rather than a canonical model, so nothing about the shared permission block changes.Round-trip note
A rewritten rule imports back under
editorreadrather than the category it was authored in. That is deliberate: the rule Claude Code applies is an Edit/Read rule, and the previous category produced no effect at all. Import stays tolerant of the legacy forms, so an existingsettings.jsonstill round-trips. Documented.Verification
pnpm cicheck(full: code + content)npx vitest run --config vitest.e2e.config.ts src/e2e/e2e-permissions.spec.tsCloses #2397