[Bug] Windows-only permission gate in 2.1.232 bypasses auto mode classifier and overrides `permissions.allow` rules
Bug Description
Title: Windows-only permission gate added in 2.1.232 bypasses the auto mode
classifier and overrides explicit permissions.allow rules
Environment
- Claude Code 2.1.232 (regressed from 2.1.220 — both binaries compared directly)
- Windows 11 Enterprise 10.0.26200, Git Bash as the Bash tool shell
- permissions.defaultMode: "auto", custom autoMode.allow configured
Summary
After updating 2.1.220 → 2.1.232, auto mode requires manual confirmation far more
often. The cause is not a stricter classifier — it is a new Windows-only gate that
prevents tool calls from reaching the classifier at all.
The new code runs after the normal permission decision, can downgrade allow →
ask, and sets classifierApprovable: false on the result. That flag means auto
mode's classifier is never consulted, so the call goes straight to a human prompt.
The function short-circuits on non-Windows (if (Yt() !== "windows" || ...) return e),
so only Windows users are affected.
Evidence this is new in 2.1.232
The marker string Cygwin-emulated occurs 0 times in the 2.1.220 binary and 3 times
in 2.1.232. cd-compound occurrences go from 3 to 5. Verified by scanning both
claude.exe binaries.
New user-visible messages in 2.1.232:
- "On Windows with Git Bash, the final working directory of this cd-compound cannot
be statically determined, so relative write targets cannot be checked for
Cygwin-emulated symlinks and this request cannot be delegated to the auto-approval
classifier."
- "This previously-approved command runs shell code from a string its security scan
cannot see into; on Windows its writes cannot be checked for Cygwin symlink
redirection and need human review."
Evidence the classifier itself is not the cause
Actual classifier denials in my local transcripts, counted per day:
| Date | Denials | Sessions |
|-------------------------|---------|----------|
| 2026-08-12 | 1 | 22 |
| 2026-08-13 | 2 | 5 |
| 2026-08-14 (post-update)| 0 | 11 |
Denials went to zero while perceived friction increased sharply — consistent with
prompts that bypass the classifier and are then approved by hand, which leave no
denial record.
Two specific behaviors that look like bugs, not intended hardening
1. permissions.allow is overridden. When probeAllowResult === true and
behavior === "allow", a command whose executable is in the shell-interpreter
sets (bash sh zsh dash ksh mksh busybox, eval source . exec trap alias let
mapfile readarray hash bind complete compgen fc coproc enable nocorrect, or
watch ionice chrt setsid taskset strace ltrace script flock unshare nsenter)
is still sent to a human prompt. An explicit user-configured allow rule is
silently discarded.
2. autoMode.allow becomes inert. Because these paths set
classifierApprovable: false, no custom auto mode rule can ever apply to them.
There is no configuration escape hatch on Windows — autoMode.classifyAllShell
only makes it worse, since it suspends all Bash/PowerShell allow rules.
Expected
A permissions.allow match should be honored, or the classifier should still be
allowed to evaluate the call. Users should have some way to opt into the previous
behavior. At minimum, the static-analysis limitation should degrade to a classifier
call rather than to an unconditional human prompt.
Actual
Windows users lose auto mode delegation for a broad class of ordinary commands —
any cd X && Y compound, anything invoking a shell by name, and any write target
that cannot be statically resolved — with no setting to restore it.
Note on scope
I confirmed the binary diff and the denial-rate change. I have not yet captured a
transcript instance of the four trigger messages, so I cannot say which trigger
dominates in practice. The code paths and the Windows-only guard are unambiguous
in the 2.1.232 bundle.
Environment Info
- Platform: win32
- Terminal: windows-terminal
- Version: 2.1.232
- Feedback ID: dabdf5a1-9512-43ef-a08d-16255c88a089
Errors
[]
3 Comments
Independent corroboration from a different machine, plus some usage data on which trigger dominates.
Environment
permissions.defaultMode: "auto"in~/.claude/settings.json, shippedautoModedefaults (no custom rules)1. The
cd-compound trigger looks dominant in practiceYou noted you hadn't captured which of the four triggers fires most. Parsing 50 recent session transcripts on this machine and splitting each
Bashcommand into segments:| Leading token | Segment count |
|---|---|
|
cd <repo-root>| 1360 ||
head| 706 ||
python| 268 ||
echo| 205 ||
tail| 135 ||
gh issue| 134 ||
git diff| 84 ||
powershell| ~30 |cd <abs-path> && <work>is by a wide margin the most common shape, because it is the natural way to pin a working directory per call. Every one of those is a cd-compound. If the static analyzer cannot resolve the final working directory of a cd-compound, that single pattern alone accounts for most tool calls in a normal session.2. The symlink check is a confirmed false positive here
Symlink-related refusals appear in this project, and the project contains no symlinks of any kind. Verified:
find . -type l→ emptycmd /c dir /AL X:\Dev→File Not Found(no NTFS junctions or reparse points)subst→ no output (not a mapped/substituted drive;X:is a physical volume)git config core.symlinks→false.gitdirectories (find . -maxdepth 3 -name .git→ empty besides the root)So the gate is not detecting an actual Cygwin-emulated symlink; it is refusing because it cannot statically prove the absence of one, and that refusal is unconditional rather than degrading to a classifier call. On a repo where the answer is trivially "there are none", this is pure friction.
3.
permissions.allowoverride reproducesThis project's
.claude/settings.local.jsonhas hadBash(git:*),Bash(python:*),Bash(powershell:*),Bash(sed:*),Bash(find:*)etc. inpermissions.allowfor months. Post-2.1.232 those entries no longer prevent prompts for the interpreter cases, matching your behavior (1).4. Interaction worth flagging: the auto-mode system prompt actively steers into the trigger
In auto mode the agent is instructed to prefer the Bash tool over the dedicated Read/Edit/Write tools, and to make file changes with
sed, heredocs, or short scripts. A heredoc write (cat > file <<EOF ... EOF) is exactly "shell code from a string its security scan cannot see into", and ased -iwith a relative target is exactly an unresolvable relative write target.The result is that auto mode's own guidance pushes work onto the two code paths 2.1.232 marks
classifierApprovable: false. Whatever the fix for the gate, these two behaviors should probably be reconciled — right now the mode that is supposed to reduce prompts is routing work into the paths that guarantee them.Practical impact
There is no allowlist workaround. I ran a full transcript-frequency analysis to build a targeted
permissions.allowlist and it produced nothing useful: every high-frequency read-only command (head,tail,git diff,gh issue,grep,find,sed -n) is already auto-allowed and was never the problem, and everything that is prompting is either a cd-compound or an interpreter, neither of which an allow rule can rescue whileclassifierApprovable: falseis set.Current escape is downgrading to 2.1.231.
Fixed in 2.1.233 — changelog: "Reverted the 2.1.232 Bash permission changes for Cygwin-style symlinks on Windows and for input redirections (
< file); a narrower version will return in a later release" (https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md). Closing — reply to reopen if it still happens on the latest version.🤖 Generated with Claude Code
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.