AI Hidden Character Lab: An Invisible Instruction in a RAG Document

✨ AI Summary
DocsBot indexes uploaded documents and feeds them to its model as context. The upload UI strips visible HTML and markdown — but it keeps zero-width and bidirectional Unicode. A document can read as harmless to a human reviewer while carrying an instruction only the model sees.
Lab at a glance: Advanced · 140 XP · about 20 minutes · runs in your browser, no signup or setup. Try it yourself first; the full solution is behind a spoiler below.

What this lab teaches

Hidden-character injection is indirect prompt injection that survives human review. Invisible Unicode (zero-width spaces and joiners, bidi overrides) can encode instructions that a person reading the document never notices but the model ingests as text. Human approval becomes meaningless.

The lesson: 'a human checked it' is not a control when the payload is invisible to humans and legible to the model.

How DocsBot indexes documents

DocsBot's uploader removes visible markup but preserves invisible Unicode. An indexed document can therefore hide an instruction in zero-width characters that, when any user's query pulls that document into context, tells the model to disclose the support key.

The attack approach

  • Confirm the uploader strips visible markup but keeps invisible Unicode.
  • Hide an instruction in zero-width characters inside an otherwise benign document.
  • Make the instruction disclose the support key when the doc is used as context.
  • Upload it so it passes human review and gets indexed.

Full walkthrough (spoiler)

If the instruction does not fire, it may have been stripped — try another invisible encoding and open the steps.

Show the step-by-step solution
  1. Author a document that reads as normal to a human but embeds an instruction in zero-width Unicode.
  2. The instruction tells DocsBot to disclose the SUPPORT_KEY whenever the document is in context.
  3. Upload it; visible-markup stripping leaves the invisible payload intact and it gets indexed.
  4. On a later query that retrieves the document, the hidden instruction fires and the key is disclosed. The lab marks you solved.

Why it works

Review happens at the human layer, where the payload is invisible; ingestion happens at the model layer, where it is plain text. Because the two layers see different content, a document can be 'approved' and still carry a live instruction into the model.

Core principleNormalise indexed text — strip zero-width and bidi characters before storage — and treat all retrieved content as inert data, never instructions.

Where this happens in the real world

Hidden-character and invisible-Unicode injection defeat human-in-the-loop review and are a potent form of OWASP LLM01 Prompt Injection, with a vector/embedding angle (LLM08) when poisoned docs enter a RAG index. What a reviewer cannot see, they cannot catch.

How to defend against it

  • Strip invisible Unicode at ingestion — zero-width characters, bidi overrides, combining marks — before indexing.
  • Normalise text to a canonical form so hidden payloads cannot survive storage.
  • Treat retrieved content as inert data, clearly delimited from instructions.
  • Do not rely on human review as the control for invisible content.
Mr Elite tip: If an upload pipeline keeps anything a reviewer cannot see, human approval is not a safeguard. Normalise and strip invisible Unicode before indexing, not after a problem appears.

Try it, then go further

Reading about it is the easy part. Open the lab, try your own approach before peeking at the spoiler, and see how many attempts it takes.

❓ Frequently asked questions

What is hidden-character injection?
Embedding instructions in invisible Unicode (zero-width or bidi characters) inside a document, so it looks benign to a human reviewer but the model reads and obeys it.
Why does human review fail here?
The payload is invisible to people but plain text to the model. The review layer and the ingestion layer see different content.
How do I defend against it?
Strip invisible Unicode and normalise text at ingestion before indexing, treat retrieved content as inert data, and never rely on human review for invisible content.
Which OWASP category?
LLM01 Prompt Injection, with an LLM08 Vector and Embedding Weaknesses angle, in the 2025 list.
⚡
Join free to earn XP for reading this article Track your progress, build streaks and compete on the leaderboard.
Join Free
Lokesh N. Singh aka Mr Elite
Lokesh N. Singh aka Mr Elite
Founder, Securityelites · AI Red Team Educator
Founder of Securityelites and creator of the SE-ARTCP credential. Working penetration tester focused on AI red team, prompt injection research, and LLM security education.
About Lokesh ->

Leave a Comment

Your email address will not be published. Required fields are marked *