GitHub - 000wq123/boundaryguard: Detect and remove invisible Unicode security hazards. Trojan Source detection, CI checks, and safe RTL handling. · GitHub
/" data-turbo-transient="true" />
Skip to content
Type / to search
Sign in<br>Sign upAppearance settings
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
000wq123
boundaryguard
Public
Notifications<br>You must be signed in to change notification settings
Fork
Star
main
BranchesTags
Go to file
CodeOpen more actions menu
Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit
History<br>2 Commits<br>2 Commits
.github/workflows
.github/workflows
boundaryguard
boundaryguard
tests
tests
.gitignore
.gitignore
LICENSE
LICENSE
README.md
README.md
pyproject.toml
pyproject.toml
View all files
Repository files navigation
boundaryguard
Detect, explain, and remove invisible Unicode security hazards from source code, logs, configuration, provenance strings, and AI inputs.
Zero dependencies. Pure standard library. CI-friendly exit codes.
Why this exists
In 2021, researchers (Boucher & Anderson, Trojan Source: Invisible Vulnerabilities) demonstrated that Unicode bidirectional control characters let attackers write source code that renders in a different order from its logical token order — so a human reviewer can approve code that does something entirely different from what it appears to do. The attack was assigned CVE-2021-42574 and affects every major language: Python, JavaScript, C/C++, Java, Rust, Go, SQL, Bash, and more.
The same invisible characters — bidi controls, bidi marks, zero-width spaces, and C0 controls — are routinely abused beyond source code:
Prompt injection — smuggling invisible instructions into text that an LLM will process.
String-comparison bypasses — "admin\u200b" vs "admin".
Log & provenance poisoning — invisible characters that corrupt hashes, keys, and audit trails.
Filter evasion — hiding disallowed content in plain sight.
boundaryguard is a focused, dependency-free tool for the detection and removal of this character class. It was extracted from the adversarial hardening of a production verification system — where a security audit found invisible-character bugs in provenance and metadata handling — and is shipped with a test corpus of published attack samples.
⚠️ Scope: boundaryguard detects and removes invisible-character obfuscation. It is not a general-purpose SAST scanner, and it does not claim to be a complete defense against all prompt injection or all supply-chain attacks. It removes one well-defined attack class — thoroughly.
Install
pip install boundaryguard
Python 3.9+. No runtime dependencies.
CLI
# Scan a file or directory<br>boundaryguard scan path/to/file.py<br>boundaryguard scan --recursive .
# CI-friendly check (exit 0 clean, exit 1 findings, exit 2 error)<br>boundaryguard check --recursive .
# Explain characters in a string<br>boundaryguard inspect "hello\u202e"
# Sanitize a file (in place, or to a new file)<br>boundaryguard sanitize input.txt -o clean.txt<br>boundaryguard sanitize config.json --policy preserve_rtl
Example
$ boundaryguard scan suspicious.py<br>suspicious.py:4:14 U+202E RIGHT-TO-LEFT OVERRIDE (RLO) [bidi_format] render='\u202e'
1 invisible-Unicode hazard(s) found (policy=security).
Exit codes
Code<br>Meaning
No hazards found
Hazards found
Usage or I/O error
Drop boundaryguard check --recursive . into your CI and never merge invisible code again.
Python API
from boundaryguard import (<br>find_suspicious,<br>explain_character,<br>sanitize,<br>contains_bidi_controls,<br>contains_zero_width,<br>scan_path,
text = "user: \u202e admin"
# Detect<br>for hazard in find_suspicious(text):<br>print(hazard.escaped, hazard.name) # U+202E RIGHT-TO-LEFT OVERRIDE
# Explain any character<br>print(explain_character("\u202e")) # U+202E RIGHT-TO-LEFT OVERRIDE (RLO) [bidi_format]
# Sanitize<br>print(repr(sanitize(text))) # 'user: admin'
# File scanning with line/column<br>for fh in scan_path("src", recursive=True):<br>print(fh.path, fh.line, fh.column, fh.hazard.name)
Policies
Unicode bidi and zero-width characters aren't inherently malicious — they're required for legitimate multilingual text. boundaryguard ships two policies so you can be strict where it matters and permissive where it doesn't.
Policy<br>Bidi formatting controls<br>Bidi marks (LRM/RLM)<br>ZWSP / BOM<br>ZWNJ / ZWJ<br>C0 controls
security (default)<br>strip<br>strip<br>strip<br>strip<br>strip
preserve_rtl<br>strip<br>keep<br>strip<br>keep<br>strip
security — for identifiers, provenance keys, hashes, and anything machine-parsed or compared. Strict is safe.
preserve_rtl — for human-facing text in Arabic, Hebrew, Persian, and Urdu, where LRM/RLM and ZWNJ/ZWJ are needed for correct rendering. The dangerous formatting controls are still removed.
What it...