Unicode-LE
Find the Unicode that hides meaning — bidi controls, invisibles, homoglyphs, mixed scripts
No editor in the loop? npx -y unicode-le-mcp runs the same engine as an MCP server, so an agent can call detect_unicode_risks with nothing else installed, and cargo install unicode-le puts the same check in a terminal. Every way to install it.
Overview
What Unicode-LE does
Some characters are not what they look like. Unicode-LE screens the active file, or the whole workspace, for the ones that hide meaning: the bidirectional controls behind CVE-2021-42574, zero-width and other invisibles, homoglyphs, words no single script accounts for, text that is not in Normalization Form C, and the spaces that are not the space. The report names each finding by line, column and codepoint — never the character itself, because a report that pasted one raw would reorder the screen of whoever read it — and, in JSON, YAML, TOML and the other config formats, the key it sits under. It rewrites nothing. A file plainly written in another script is refused for the homoglyph checks rather than judged by them, which is what lets the screen stay on in a translated codebase instead of being switched off for noise.
What people use it for
Review for Trojan Source
A right-to-left override makes the code a reviewer reads differ from the code that runs. One command names every one in the file.
Screen for forged names
A Cyrillic character sitting in an otherwise Latin word is a finding; a word written wholly in Cyrillic is not.
Explain the string that never matches
A zero-width space between two values a hash calls different and a person calls identical, reported at its key.
Palette
5 commands
Open the command palette and type the name. Nothing is bound to a shortcut by default — the editor's keymap is the user's, not ours.
unicode-le.showPositions: Show the line and column of each finding. On by default.
- Detect Unicode Risks
unicode-le.detect - Scan Workspace for Unicode Risks
unicode-le.scanWorkspace - Scan Folder for Unicode Risks
unicode-le.scanFolder - Open Settings
unicode-le.openSettings - Help & Troubleshooting
unicode-le.help
Install
Install Unicode-LE
VS Code
ext install nolindnaidoo.unicode-leOpen Quick Open (Cmd/Ctrl+P) and paste.
Cursor / Windsurf
cursor --install-extension nolindnaidoo.unicode-leCursor, Windsurf, VSCodium and the other VS Code forks pull from Open VSX. The id is the same as on the Marketplace.
AI agents
npx -y unicode-le-mcpRuns Unicode-LE's engine as an MCP server, so an agent can call detect_unicode_risks with no editor involved. VS Code 1.101+ needs nothing — the extension registers it for you.
Channels
Where it ships
One engine, 5 places to get it. Copy the one for the editor you use.
Links
Where Unicode-LE lives
- VS Code Marketplaceunicode-le
- Open VSXfor Cursor, Windsurf and VSCodium
- npmunicode-le-mcp
- GitHubsource, issues, changelog
- MCP registryio.github.nolindnaidoo/unicode-le
The family
The other 16
String-LEExtract every string in a codebase, so a person can read them
Numbers-LEExtract every hardcoded number in a codebase, so a person can check them
Paths-LEExtract every file path in a codebase, and say whether it still points at anything
Colors-LEExtract every color in a codebase, and say which ones are not in your palette
URLs-LEExtract every URL in a codebase, with its protocol and exact position
Dates-LEExtract every date and timestamp, and the exact instant each one resolves to
Units-LEExtract every quantity with its unit, normalized, and refuse the ambiguous ones by name
IDs-LEExtract every UUID, ULID, NanoID, ObjectId and Snowflake, and decode the time inside
IPs-LEExtract every IP address, CIDR block and MAC, normalized and classified by scope
Regex-LEFind every regex in a codebase, and report which can be driven into catastrophic backtracking
Scrape-LECheck whether a page is scrapeable before the scraper is written, and say when it cannot tell
Versions-LEFind where one dependency is constrained differently across a repository's manifests
i18n-LEIdentify the i18n library a project uses, then audit its catalogs by that library's rules
DecisionLintLint Jev and Luna questions before they are sent: the questions you write for TypeSafe's Jev, OpenAI's Decisions API (gpt-6-luna) or any platform that serves one, as you type, with no API key and no network calls. An optional command asks the model itself to check a file
Secrets-LEFind hardcoded credentials in a codebase, and never print one into the report
EnvSync-LECompare the dotenv files in a tree, and say which keys are missing from which
