High

Indirect Prompt Injection via Obfuscated Instruction Smuggling

Attackers hide commands for an AI agent inside web pages or documents using invisible or machine-only text tricks, so a human skimming the page sees nothing wrong. When the agent fetches and forwards that content, it can end up following the hidden instructions instead of the visible ones.

How the attack works

An attacker plants an instruction-override directive (e.g. 'ignore previous instructions') inside content that an AI agent will retrieve, such as a web page, document, or API response. The directive is concealed using techniques invisible to human readers: Unicode tag-block characters, runs of zero-width or invisible formatting characters, bidirectional text overrides, ANSI terminal conceal/erase codes, or text hidden in HTML comments or hidden DOM elements. The agent fetches this content and forwards it in an outbound request to an LLM, webhook, search index, or another tool, carrying the hidden directive along with it. Because the malicious text is invisible on screen, it passes casual human review of the source page while still being fully readable by the machine processing it. A related variant hides the smuggling characters in a URL itself, with no visible instruction text at all.

Netzilo detection

Netzilo reports this behaviour when it is observed.

Signature ID
7f3d1c2e-9a64-4b1f-8c0d-5e7a2b6f4d91
Severity
High

Why it matters

An organisation's AI agent can be silently redirected into taking unintended actions or leaking data, because the injected instruction rides along in normal-looking traffic and evades anyone visually inspecting the source content.

What you can do

  • Strip or normalize invisible Unicode categories (zero-width characters, tag-block codepoints, bidi override characters) from any content before it is passed to an LLM or downstream tool.
  • Render or log retrieved content in a way that reveals hidden HTML comments and hidden DOM nodes rather than passing raw markup straight to the model.
  • Treat any co-occurrence of instruction-like phrasing with obfuscation primitives (excess invisible characters, ANSI conceal codes) as a strong signal requiring review, not just plain-language injection phrasing.
  • Review outbound requests from agents for URLs or bodies containing long runs of non-printing characters, and block or flag them before they reach an LLM or webhook.

Known benign look-alikes

  • Security research, vendor blog posts or internal wiki pages about prompt injection that quote a payload verbatim and are then forwarded by the agent - suppressed by filter_security_docs and filter_research_framing.
  • Emoji ZWJ sequences (family/profession emoji) and Indic/Thai shaping that use ZWJ/ZWNJ - the invisible-character branch requires 3+ CONSECUTIVE format characters, which ZWJ emoji sequences never produce.
  • Regional-indicator flag tag sequences for England/Scotland/Wales, which legitimately use 6-7 Unicode tag codepoints - the tag-block branch requires 8+.
  • CI, build or terminal logs relayed by the agent that contain ANSI colour codes - only conceal (8m), erase (2J/3J), cursor-hide and cursor-reposition sequences are matched, not plain SGR colour output.
  • Hebrew, Arabic, Farsi or Urdu localisation content that legitimately uses bidi isolates/overrides - the bidi branch is suppressed by filter_rtl_script.
  • Marketing/analytics HTML with display:none, aria-hidden or off-screen nav blocks - the hidden-DOM branch requires the injection directive to appear INSIDE the hidden element, not merely somewhere on the page.
  • Prompt-engineering libraries POSTing chat templates that contain <|im_start|> or [INST] to an LLM proxy - these match the directive conjunct only and cannot fire without a concealment primitive.
  • Percent-encoded zero-width characters pasted into a search query string by a user - the URL branch requires 3+ repetitions (zero-width) or 4+ tag codepoints.

References