Unicode confusable characters can bypass permission rule matching
What variant of Claude Code are you using?
CLI (v2.1.62)
What feature would you like to see?
Summary
The permission system matches tool invocations against string-based allow rules (e.g. Bash(git:*), Read(~/.zshrc), Edit(/Users/pw/Code/**)). These comparisons do not normalise Unicode, which means a crafted file path or command containing visually identical confusable characters could bypass permission checks.
For example:
- A path containing Cyrillic
а(U+0430) instead of Latina(U+0061) would not match an allow rule written with ASCII characters, but would look identical to the user in terminal output. - Conversely, a deny rule targeting a specific path could be evaded by substituting confusable characters that render identically but fail the string match.
This is a known class of attack in package registries (typosquatting via homoglyphs) and identity systems (IDN homograph attacks). The same principle applies to any security boundary that relies on string comparison of user-visible identifiers.
Proposed solution
Canonicalise both the permission rule and the tool invocation argument before comparison. This could be done with:
- Unicode NFKC normalisation as a baseline (collapses compatibility equivalents).
- Skeleton matching (as defined in Unicode TR39) to catch cross-script confusables that NFKC misses.
- Mixed-script detection to flag inputs that combine characters from multiple scripts (e.g. Latin + Cyrillic), which is almost always either an attack or an error.
The open source library namespace-guard (MIT, zero dependencies, TypeScript) provides canonicalise(), scan(), and confusableDistance() functions built on confusable-vision weight data. The weight data covers 1,397 confusable pairs including 793 pairs not in the Unicode consortium's TR39 list, discovered by rendering 26.5M character pairs across 230 fonts and measuring structural similarity (SSIM).
Affected components
- Permission rule matching (
area:permissions) - File path arguments passed to Read, Edit, Write tools
- Command strings passed to the Bash tool
- MCP server URIs and tool names
Alternatives considered
- NFC/NFD normalisation only: insufficient; does not catch cross-script confusables (Cyrillic а vs Latin a are already in NFC).
- Rejecting all non-ASCII: too aggressive; legitimate file paths contain accented characters, CJK, etc.
- Warning instead of blocking: a reasonable first step; flag mixed-script paths to the user without hard-blocking.
Priority and scope
This is a defence-in-depth measure. Exploiting it requires either a malicious prompt injection that crafts confusable paths, or a pre-existing file on disk with confusable characters in its name. The attack surface is real but narrow. A warning-based approach (flagging mixed-script inputs) would be a proportionate first step.
Additional information
No existing issues on this repo cover Unicode confusable attacks on the permission system. Searched for "unicode confusable", "homoglyph", and "permission bypass" on 2026-02-28; the existing permission bypass issues (#16180, #25168, #20262) relate to command chaining and tool execution ordering, not Unicode normalisation.
Environment: macOS Darwin 25.2.0, Claude Code v2.1.62
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗