[BUG] Windows (CJK locale): permission rules with non-ASCII prefix never match; "Always allow" persists mojibake rules; backslashes double on every settings rewrite
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
On a CJK-locale Windows machine (system ANSI codepage 950 / Big5, Traditional Chinese), the permission system mishandles non-ASCII characters end-to-end, producing three compounding failures:
- Allow rules whose command prefix contains CJK characters never match the byte-identical command, so every whitelisted script call prompts again. In our sessions the same whitelisted scripts prompted 5/5 times, and again 3/3 after an app restart + update.
- Clicking "Always allow" persists the rule into
.claude/settings.local.jsonwith the CJK bytes encoded in the ANSI codepage (Big5) instead of UTF-8 — the saved rule is mojibake inside an otherwise-UTF-8 file, can never match, and silently does nothing. Approving again just accumulates dead duplicates. - Every time the app appends a new rule it re-serializes existing entries and doubles their backslashes (
\\→\\\\), progressively corrupting the file. Long-lived files contain entries with 4–6 backslashes and permanently lost CJK (U+FFFD replacement chars).
The defect is isolated to the rule side: an allow rule whose prefix is pure ASCII (e.g. PowerShell(Test-Path *)) silently matches a command whose arguments contain CJK paths — verified in the same session. Only rules whose prefix itself contains CJK never match.
Net effect: permission allowlists are unusable for any user whose paths contain Chinese/Japanese/Korean characters (the common case for zh/ja/ko users), and the file meant to remember approvals rots a little more with each approval.
Environment: Windows 11 Home 10.0.26200 · system locale zh-TW (ANSI codepage 950) · Claude Code desktop app v1.18286.0 (also reproduced on the build immediately before) · PowerShell 5.1 · project path contains CJK characters.
What Should Happen?
- Rules and commands are compared as Unicode strings (ideally NFC-normalized), regardless of the machine's ANSI codepage — a rule containing 工作區 should match a command containing 工作區.
- "Always allow" persists rules as UTF-8, byte-faithful to the approved command, so the approval is actually remembered.
- Re-serialization of the settings file is idempotent — appending rule N must not mutate rules 1..N-1 (no backslash doubling).
- If a stored rule contains invalid UTF-8 / U+FFFD or fails to parse, surface a warning instead of silently never matching.
Error Messages/Logs
Rule as written by "Always allow" into .claude/settings.local.json — the CJK folder name 工作區 was stored as ANSI/Big5 bytes, which render as mojibake when the file is read as UTF-8:
"PowerShell(C:\\Users\\<USER>\\Documents\\claude�u�@��\\tools\\hello.ps1 -Source \"C:\\Users\\<USER>\\Documents\\claude�u�@��\\docs\\�}�o�F���@���s.md\")"
(�u�@�� is exactly the Big5 byte sequence A4 75 A7 40 B0 CF for 工作區 mis-decoded as UTF-8 — each invalid byte becomes U+FFFD.)
After clicking "Always allow" on any unrelated later command, previously saved entries in the same file are rewritten with doubled backslashes:
before: "PowerShell(C:\\Users\\<USER>\\..."
after: "PowerShell(C:\\\\Users\\\\<USER>\\\\..."
Entries that have survived several rewrites show 4–6 backslashes per separator.
Steps to Reproduce
- Windows machine with system ANSI codepage 950 (Traditional Chinese locale; the same class of bug should reproduce with 932/936/949).
- Create a trivial script at a CJK path, e.g.
C:\Users\<USER>\Documents\工作區\tools\hello.ps1. - Add to
~/.claude/settings.json→permissions.allow:"PowerShell(C:\\Users\\<USER>\\Documents\\工作區\\tools\\hello.ps1 *)"(file saved as valid UTF-8; the CJK renders correctly when read back). - Start a NEW session (settings load at session start). Ask Claude to run the script by full path — the command string is byte-identical to the rule prefix.
- BUG 1: a permission prompt appears anyway; repeats on every call.
- Click "Always allow", then open
.claude/settings.local.jsonin a hex/UTF-8 editor. - BUG 2: the newly saved rule's CJK segments are ANSI/Big5 bytes inside an otherwise-UTF-8 file (mojibake); the rule never matches; the next identical command prompts again.
- Trigger any unrelated approval so the app appends another rule.
- BUG 3: previously saved entries are rewritten with doubled backslashes (
C:\\Users→C:\\\\Users).
Control probes (isolate the defect):
Get-Date -Format ...with ASCII rulePowerShell(Get-Date *)→ no prompt (engine works).Test-Path "C:\...\工作區\file.md"(CJK argument) with ASCII rulePowerShell(Test-Path *)→ no prompt (command-side CJK is fine).- Only rules whose PREFIX contains CJK fail.
Mitigations already attempted (all verified, none helped): bare-path and & "..." rule forms; byte-identical calling convention; fresh session after every settings change; full app restart; applying the pending update; additionalDirectories including the CJK workspace; repeated "Always allow". Working workaround: an ASCII-only NTFS junction pointing at the CJK folder + ASCII-prefix rules.
Claude Model
None
Is this a regression?
Yes, this worked in a previous version
Last Working Version
exact number unknown — the build in use on 2026-07-02 (one update earlier): same CJK rules matched with zero prompts
Claude Code Version
2.1.186 (Claude Code) — Windows desktop app v1.18286.0
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
PowerShell
Additional Information
Closely related existing issues (same defect family):
- #46783 — Windows: permission prompt generates backslash allow-rules that never match forward-slash Bash commands (allow-rule written in a form that can never match — ours is the encoding variant)
- #46486 — PowerShell output displays garbled text on Windows when system codepage is Big5 (950) (same CP950-vs-UTF-8 root cause, different surface)
- #7332 / #7134 — encoding-handling class (garbled Chinese output; Windows-1252 file corruption)
Suggested fixes:
- Persist settings explicitly as UTF-8 on Windows (matching how the file is read); on read, tolerate and repair legacy ANSI bytes.
- Normalize both rule prefix and incoming command (NFC) before prefix matching; add a regression test with a CJK path on a CP950 runner.
- Make re-serialization idempotent (parse → modify → stringify through one JSON path); add a round-trip test asserting appended rules leave existing entries byte-identical.
- Surface dead rules: if a stored rule contains invalid UTF-8 / U+FFFD, warn in the permission UI instead of silently never matching.
Impact: autonomous pipelines built on full-path allowlists (fixed backup/test/convert scripts) are fully blocked for users with non-ASCII project paths; "Always allow" is a silent no-op for them and corrupts the settings file over time.
Full local session transcripts of 2026-07-03 available on request (5-prompt run, then 3-prompt run after restart+update; before/after copies of the corrupted settings.local.json).