Skip to content

Invisible characters in email: the AI trick has moved to phishing, and the hole is in your code

Published on 7 September 2026

Sobre abierto con letras de imprenta sueltas y huecos entre ellas; detrás, la silueta de espaldas de una persona con una lupa sobre una hoja en blanco.

A trick born in AI security research has just turned up in bog-standard phishing. And the practical lesson isn't for your mail filter: it's for every place in your code where you compare strings.

What happened

Microsoft researchers Noam Kochavi and Sarah Wolstencroft published an analysis on Thursday of a phishing campaign using ASCII smuggling: slipping Unicode characters that don't render on screen inside text that looks perfectly normal to a human.

The numbers, as they report them:

  • The detection signature fires in early February: around 21,000 messages flagged on 8 February, and more than 1.3 million the next day.
  • An intense phase with weekday volumes between 1 and 2.37 million messages, peaking on 26 February.
  • By late March, roughly 80% less per weekday. A sharp drop after 15 May, with occasional smaller spikes through mid-June.
  • About 150 finance-themed sender domains.
  • A very distinct rhythm: bulk sending Monday to Friday, silence at weekends.

The striking bit is what the invisible characters were for. In indirect prompt injection, an attacker hides instructions for an assistant in code points a human can't see but a model happily decodes. Here there was none of that:

"The surprise was that there were no hidden instructions aimed at an AI assistant."

Instead, they inserted Unicode tag spaces inside common financial words to split them apart: fun + U+E0020 + ding instead of "funding". The reader sees the whole word. Your regex doesn't.

Why it matters

Because the flaw isn't in Unicode or in email: it's in the habit of comparing raw text with literal rules. And we all do that far more often than we remember.

Think about where you have string comparisons that decide something in your product: banned-word lists on a form, anti-fraud rules over a transfer's reference text, record deduplication, internal search, comment moderation, username or domain validation, secret scanning before a commit, invoice or subject-line classification. In every one of those places, a character that never gets painted on screen breaks the match without anyone noticing a thing.

Microsoft's recommendation is exactly that, and it's the part I care about: make sure your normalisation and tokenisation pipelines handle tag characters consistently, and that anything to be evaluated by keyword, signature or regex first goes through a step that strips or folds invisible code points.

How I'd build it, concretely:

  1. One single normalisation point at the input boundary. Don't normalise at each comparison: that guarantees someone forgets on the third one. One helper that everything from outside passes through.
  2. What that helper strips: the tag block U+E0000U+E007F, zero-width characters (U+200BU+200D, U+FEFF), bidi controls (U+202AU+202E, U+2066U+2069) and, depending on the case, variation selectors. On top, NFKC normalisation to unify compatibility forms.
  3. Keep both versions. Compare against the normalised one, store and display the original. Throw the original away and you lose the evidence and break legitimate data.
  4. Count, don't just clean. "How many invisible code points did this text carry" is dirt cheap to compute and a great signal: a normal email subject carries zero.
  5. Make your log viewer show them. If the attacker hides them from the human eye, your review panel hides them too. A mode that escapes non-printables as hex saves you an afternoon of "but it says the same thing".

There are two wider readings. First: if your assistant ingests email, documents or web pages, that same filter is your first layer against indirect injection. It's free, use it. Second is organisational: the technique came from the AI world and landed in classic spam. If in your shop "AI stuff" is one person's job and email is another's, this crossover falls straight down the gap. At Black Wings, being one person, at least I don't have that problem.

The other gift in the report is that the best indicator wasn't the content but the shape: huge weekday volume, nothing at weekends, freshly churned disposable domains, all finance-themed. You can copy that pattern into your own anti-fraud without touching a single keyword.

What doesn't change

Let's be honest about the size of this story.

  • It's not a vulnerability or an exploit. Unicode does what it's documented to do. This is signature evasion, not code execution.
  • It doesn't make the con more effective on the victim. The person reads exactly what they'd read without the trick. What's under attack is your filter, not their judgement.
  • Normalising doesn't stop phishing. It only restores whatever effectiveness literal matching had, which wasn't much. Keyword filtering was a weak defence before this and still is.
  • Don't bulldoze the tag block blindly. The England, Scotland and Wales flags are encoded with tag characters. If your product renders emoji, that stripping can't be applied to text you're about to display. Normalise for comparison, not necessarily for storage and display.
  • This doesn't solve prompt injection. The underlying problem is that the model can't tell data from instructions; removing invisibles closes one hiding channel, not the attack. Perfectly visible text still works.
  • There's no attribution and we don't know whether the campaign paid off. Microsoft reports what it saw in its telemetry, and good on them for reporting it.

If your product has text comparisons that decide something — charge, block, approve, deduplicate — this is a good week to look at where that text comes in. Any questions, tell me and we'll go through it.

All the best, Vicente.

Source: The Register

Did reading this raise a question?

Ask us. We answer even if you never become a client.