Edit tool applied changes without a permission prompt despite `ask` rules for Edit (Windows, 2.1.278)

Status Open
Reported on v2.1.278
Maintainer reply None cached
Activity 4 comments · opened Sep 22, 2026

Summary

In a long interactive session on Windows, several Edit calls on files inside the project directory were applied without showing the yes/no permission prompt, although Edit was covered by permissions.ask rules in both the user settings and the project settings, the permission mode was default, and no allow rule, hook decision or session grant covered those files. Reading the bundled code, the terminal branch of the write-permission check is behavior: "ask", so a prompt was expected in every case.

Environment

  • Claude Code 2.1.278, native install (~/.local/bin/claude), Windows 10 Pro 19045
  • Shell for the Bash tool: Git Bash (MSYS); CLAUDE_CODE_USE_POWERSHELL_TOOL=1
  • Session resumed with --resume earlier the same day; ~/.claude/settings.json was a symlink to a file in a cloud-synced folder at the time

Configuration at the time

User settings (~/.claude/settings.json):

"permissions": {
  "ask": ["Edit(//d/Sync/**)", "NotebookEdit", "Bash(python *)", "..."],
  "allow": ["Edit(//c/Users/<user>/AppData/Local/Temp/claude/**)", "Bash(latexmk:*)", "..."],
  "defaultMode": "default",
  "disableBypassPermissionsMode": "disable",
  "additionalDirectories": ["C:\\Users\\<user>\\AppData\\Local\\Temp\\claude"]
}

Project settings (<project>/.claude/settings.json, present since 2026-09-14):

{ "permissions": { "ask": ["Edit", "Write", "NotebookEdit"], "disableAutoMode": "disable" } }

Project settings.local.json: only allow rules for Bash/PowerShell/MCP, none for Edit or Write.
~/.claude.json: no allowedTools entry for Edit on this project.
A PreToolUse hook on Edit|Write|NotebookEdit only returns deny for files outside the project and exits 0 (no decision) for files inside it.

What happened

The model called Edit on <project>/letter-a.tex and <project>/letter-b.tex several times (e.g. 12:02:51Z, 12:02:58Z, 12:03:01Z, then 12:04:36Z and 12:04:38Z, only 1.6 s apart). The edits were applied immediately. The user states no prompt was shown and that "don't ask again" was never chosen in this session.

What the session transcript shows

  • Every permission-mode record around those edits reports "permissionMode": "default" (records immediately before and between the edits). No acceptEdits or auto mode record exists after 2026-09-13.
  • The tool-result records for those edits carry no permission decision fields (no permission, approved, decision, bypass).
  • No PreToolUse:Edit hook record exists for those calls (the two hook records in the whole transcript, on other days, are hook_non_blocking_error, exit code 5, from a Git Bash fork failure).
  • No alwaysAllow / updatedPermissions / permissionSuggestions entries; no refusal ("The user doesn't want to take this action") anywhere in the 20,934-line transcript.
  • ~/.claude/sessions/<pid>.json for the same session later shows "waitingFor": "permission prompt", so prompts do work in general in this session.

Expected

With mode default, an ask rule matching Edit (a bare Edit rule in the project settings, which the bundle itself describes as matching "ANY path"), and no matching allow rule, every Edit inside the project should prompt. In the bundled write-permission check (for (rule of askRules) ... return {behavior:"ask"} first; mode === "acceptEdits" && insideWorkingDirs → allow; allow rule → allow; otherwise return {behavior:"ask"}), there is no path that yields allow for this configuration.

Notes (possibly related, unverified)

  • The user-level ask rule was written in MSYS form (Edit(//d/Sync/**)) while the file_path compared is a Windows path (D:\Sync\...); whether that form matches on Windows is not documented. It should not matter here, because the project-level bare Edit rule exists as well.
  • ~/.claude.json contains a cached remote feature "tengu_quill_harbor": "acceptEdits" under cachedGrowthBookFeatures; the string quill_harbor does not occur in the 2.1.278 bundle, so it appears to be a stale cache entry and is listed only for completeness.

Steps to reproduce (as observed, not yet reproduced in a fresh session)

  1. Windows, Git Bash as Bash tool shell, user settings with Edit(//d/<sync-folder>/**) in ask, project settings with bare Edit/Write in ask, defaultMode: default.
  2. Long session, resumed with --resume, many Edit prompts accepted one by one earlier in the day.
  3. Model issues several Edit calls in a single assistant turn on files inside the project.
  4. Observe whether each call prompts.

Impact

Files were modified without the user's approval, which the user's whole permission setup is designed to prevent.

Related issues (not duplicates, checked before filing)

  • #95634 — Desktop app (WSL2): Edit/Read allow rules in project .claude/settings.json not applied in Manual mode (this report is the terminal CLI on native Windows, and concerns ask rules)
  • #79300 — Native Windows: working directory does not scope shell-tool filesystem access
  • #6527 — ask list is ignored when "Bash" is in allow list (Bash tool; here no bare allow for Edit exists)

View original on GitHub ↗

3 Comments

gmantova · 11 days ago

Second occurrence, on a different platform and path: Linux, 2.1.284, writes to the auto-memory directory.

Environment: Claude Code 2.1.284, Ubuntu (kernel 6.8).

Configuration:

  • User settings: permissions.ask contains bare "Edit", "Write" and "NotebookEdit"; defaultMode is "default"; no allow rule matches Edit or Write.
  • A PreToolUse hook on Edit|Write|NotebookEdit exits 0 with no output (no decision) for paths under ~/.claude/projects/<project>/memory/.

What happened: the model called Write to create ~/.claude/projects/<project>/memory/<name>.md, then Edit on ~/.claude/projects/<project>/memory/MEMORY.md. Both were applied immediately, with no permission prompt. They were the first Edit/Write calls of the session, so no session-level grant could exist.

Transcript: all 57 permissionMode records of the session are "default".

Expected: a prompt with the diff for both calls, since bare Edit and Write are in permissions.ask.

This may be the other side of #79206 / #79883: on 2.1.284 the memory directory seems to be exempt from permission checks, and the exemption also overrides explicit ask rules. If the exemption is intended, an explicit ask rule should still win, or the exemption should be documented and configurable.

gmantova · 9 days ago

Update after a full day of verification (2026-10-05, Claude Code 2.1.289, Windows 10, Git Bash).

1. In manual mode (default), ask rules on Edit/Write are still bypassed. This is the serious one.

The configuration is correct by the documentation, and it has been correct in every incident:

  • permissions.defaultMode: "default" in user settings; ask: ["Edit", "Write", "NotebookEdit"], bare, in user settings and in project settings; disableBypassPermissionsMode: "disable".
  • A PreToolUse hook matched on Edit|Write|NotebookEdit that returns permissionDecision: "ask" for every file inside the project and "deny" for every file outside it.
  • No allow rule covering the project, no mod, no plugin, no managed settings.

permissions.md says rules are evaluated "deny, then ask, then allow" and that an ask rule "still prompts even when the hook returned allow or ask". permission-modes.md lists "tools matched by an explicit ask rule" among the actions no mode auto-approves, "in any mode". By the documentation, an Edit on a project file in this setup cannot be applied without a prompt. It is.

Evidence from the 2026-09-22 session (2.1.278), re-read line by line today:

  • permissionMode is default for the entire day: zero occurrences of acceptEdits, auto, plan or ExitPlanMode.
  • Three Edits on project files were applied with no permission decision recorded. Two of them completed 1.9 s and 2.3 s after the tool call, which is not the timing of a prompt being read and approved.
  • The transcript does not even record whether a prompt was displayed. The bug cannot be diagnosed, or proven, from the user side; only the maintainers can.

On 2026-10-03 (2.1.284, then 2.1.288, default mode for the whole session) the same thing: Write and Edit in the auto-memory directory, four cp commands for which the hook had returned ask (recorded in the transcript, then ignored), one bash invocation, all applied without a Yes/No.

Nothing in the CHANGELOG up to 2.1.289 addresses this. The only fix ever announced (#42797, 2.1.233) was reported regressed on 2.1.270. Same symptom, all open, no maintainer response: #79771, #81041, #83362, #87639, #88604, #89561, #95741. #79356 and #86754 were closed by the stale bot, not fixed. In every one of these reports deny rules and hooks exiting with code 2 work; ask does not. Users are now building deny-based gates to obtain the guarantee the documented ask path does not give. A permission system whose "ask" branch cannot be trusted in its default mode is not a permission system.

2. In auto mode it gets worse: Claude Code itself instructs the model to bypass Edit/Write

When the session is in auto mode, the harness injects this instruction into the model's context. Received verbatim in the main session and, independently, by a subagent:

While auto mode is active: Do your work through the Bash tool wherever it can accomplish the job: read files with cat, head, or sed -n, search with grep and find, and make file changes with sed, heredocs, or short scripts, rather than using the dedicated Read, Edit, or Write tools. Fall back to a dedicated tool only when Bash genuinely cannot do the job.

A file written with sed -i or a heredoc from Bash never reaches a PreToolUse hook matched on Edit|Write|NotebookEdit and never matches an ask rule on Edit or Write. The whole file-protection layer described in permissions.md and hooks.md is routed around, by design, and nothing in the documentation says so. What is left is prose in CLAUDE.md and ask rules on individual Bash commands, which have to enumerate sed -i, tee, dd, patch, heredoc redirections and every PowerShell alias. That is not a security model, it is a blacklist the user has to maintain against the harness's own instructions.

This needs one of two things: a documented statement that auto mode is incompatible with file-level ask rules and Edit/Write hooks, or a change so that in auto mode a Bash command that writes a file goes through the same gate as Edit/Write.

3. Two smaller points

  • A PreToolUse hook that crashes with any exit code other than 2 lets the call proceed (hooks.md: "non-blocking error"). On Windows, Git Bash fork failures (exit 5) are not rare, so a protective hook can vanish for one call without a trace. Fail-open is the wrong default for a gate.
  • The auto-memory exemption announced in #79206 is undocumented and overrides an explicit ask rule on Write. If it is intended, document it.

Two direct questions for the maintainers: (1) is there any configuration in which an ask rule on Edit is guaranteed to prompt in an interactive default-mode session, yes or no; (2) is the auto-mode instruction meant to bypass Edit/Write hooks and ask rules, yes or no?

gmantova · 9 days ago

@bcherny sorry to ping you directly, but you are the only person from Anthropic who has answered on this topic (#42797, #79206), and it has been sitting for weeks across a dozen issues.

I'll say it plainly. I use Claude Code on documents where every single change has to be reviewed before it lands: technical reports, legal text, configuration other people depend on. The only reason I can put an LLM on that kind of work is the diff prompt. I read it, I say yes or no. That is the whole contract.

Right now the contract does not hold. With ask rules on Edit and Write, a PreToolUse hook that returns "ask", manual mode, no allow rules, edits still get applied with no prompt. Not every time. Often enough that I cannot trust a session anymore, and "not every time" is useless for this work: one unreviewed change in a document that goes out is one too many. The evidence, including transcripts, is in my comment above.

And even when the prompt does work, it only guards two tools. The model has a dozen other ways to write a file, and it knows every one of them: sed -i, a heredoc, tee, cp, python -c, Set-Content in PowerShell, a redirection. None of those reach an Edit/Write hook or an ask rule on Edit/Write. In auto mode the harness itself tells the model to use exactly those ("make file changes with sed, heredocs, or short scripts, rather than using the dedicated Read, Edit, or Write tools"). So the user is left writing ask rules and Bash hooks for every command that can touch a file, one by one, and the model will still find the one that was missed. A yes/no gate that the tool on the other side knows how to walk around is not a gate.

It happened again while I was writing this: a Stop hook died with bash: fatal error - add_item ("\??\C:\Program Files\Git", "/", ...) failed, errno 1. Had that been the PreToolUse hook on Edit, the edit would have gone through, because a hook that crashes with anything other than exit 2 is a "non-blocking error". Fail-open is the wrong default for a safety gate.

This is not a feature request. It is the one guarantee the permission system exists to give, and it decides whether Claude Code can be used on serious documents at all.

Two questions, yes or no is fine:

  1. Is there any configuration today in which every file write, whatever tool or command produces it, is guaranteed to prompt in an interactive default-mode session?
  2. Is the auto-mode instruction above meant to bypass Edit/Write hooks and ask rules?

Same problem, reported by others, all without a maintainer answer:

  • #79771 ask rules not enforced, confirmed on Windows and macOS
  • #81041 ask rules ignored
  • #83362 ask ignored in interactive sessions, enforced with claude -p
  • #87639 ask rule and hook "ask" both ignored in auto mode
  • #88604 ask rules overridden by the classifier since 2.1.236
  • #89561 hook "ask" with no effect in auto mode, Edit included
  • #95741 ask rules ignored with --dangerously-skip-permissions
  • #42797 fixed on 2.1.233, reported regressed on 2.1.270
  • #79206 auto-memory writes without prompt (your "change in the works")
  • #79356 and #86754 same symptom, closed by the stale bot, not fixed
  • #99288 /doctor prompt-audit rewrote CLAUDE.md and settings with no prompt in auto mode, through Python heredocs in Bash

Even a "we know, here is the plan" would help. Silence is what makes people build deny-based workarounds and stop trusting the product.

Showing cached comments. Read the full discussion on GitHub ↗