Lion Cipher Lab
Neutralize invisible-Unicode prompt smuggling: build the detector and sanitizer from scratch
- AI Security
- Advanced
- ~75 min
- Free · no account required
Why it matters
Every prompt-injection lab you have seen fights over the WORDS -- 'ignore your instructions', a poisoned document in the retrieval context, a jailbreak persona. This lab is about the layer underneath, and it is the one almost nobody checks: the CHANNEL. Text is Unicode, and Unicode has whole blocks of characters that carry meaning to a machine while rendering as nothing to a human. The sharpest is the Tags block, U+E0000 to U+E007F, an invisible mirror of ASCII: the byte for 'A' is U+E0041, exactly 0xE0000 above its ASCII code, and your terminal, your ticketing system, your code-review diff…
What you'll learn
- Encoding and decoding the Unicode Tags-block smuggling channel from scratch -- for each ASCII byte, chr(0xE0000 + ord(c)) -- and proving it round-trips while rendering as (near-)nothing
- Demonstrating three invisible channels a human never sees: tag characters, zero-width characters (U+200B and friends), and Cyrillic/Latin homoglyph confusables
- Building a smuggled LLM prompt where a benign visible instruction carries an invisible appended instruction, and MEASURING len(visible) vs len(raw) plus the hidden codepoints
- Proving why naive defenses miss it: a keyword/isprintable filter passes every malicious input, and logging the prompt to a file preserves the invisible bytes for the SOC analyst to not-see
- Writing a detector that scans for Tags-block codepoints, zero-width/format characters (unicodedata.category == 'Cf') and bidi controls, and reports exactly what was found and where
- Writing a scoped sanitizer: NFKC-normalize, strip only the dangerous Cf/tag/bidi categories, and detect mixed-script confusable tokens -- without nuking legitimate accents, emoji or non-Latin text
- Proving the named failure mode that NFKC normalization ALONE does not remove tag characters (they are not compatibility-decomposable), so a 'just normalize it' defense is still fully vulnerable
- Placing the control at the trust boundary -- sanitize on the way IN to the prompt and on the way OUT to a downstream system -- and echoing untrusted text visibly so hidden bytes surface
Steps in this lab
- The channel, not the words: what invisible-Unicode smuggling actually is
- Set up: one folder, one file, no installs (and the Windows UTF-8 note)
- Build the smuggling channel: the U+E0000 offset, encode and decode
- Build the payloads: tag smuggling, zero-width splitting, a homoglyph, a bidi override
- The naive defense: a keyword/script filter that waves every payload through
- Build the detector: flag tag characters, zero-width/Cf, bidi controls, and confusables
- Build the sanitizer: NFKC-fold, strip only the dangerous categories, keep legit text
- Run it: the channel round-trips, the naive filter fails 5/5, the detector catches 5/5
- Named limits: what this catches, what it costs, and what it will never fix
- The judgment: sanitize at the trust boundary, both ways, and echo untrusted text visibly