skip to content

Why is 'we normalise input, so hidden characters are gone' an incomplete claim against a carrier-choosing attacker?

level: juniorimportance: must knowfreq 78%

answer

  1. naming a pass is not coverage
  2. it removes a defined set
  3. everything outside the set survives
  4. attacker picks from the remainder

basics

~20 s

A normalising pass removes a specific, enumerable set of carriers, not everything a span could hide in. 'We normalise' names that a pass runs; it does not say which carriers it strips and which it keeps. The attacker just picks a carrier from what survives.

solid answer

~50 s

Normalisation is a set-removal step: it targets a defined group of things, say a list of zero-width or control codepoints or a chosen Unicode form, and leaves everything outside that group untouched. A homoglyph the map does not fold, text baked into an image, a metadata field the normaliser never receives on that path, all pass straight through. So `we normalise` and `we remove these codepoints, and here is the list of carriers we keep` are different claims: the first is a verb, the second is a coverage statement you can test. An attacker treats the normaliser as one filter with a known blind spot and chooses a carrier from the remainder. The honest security answer is the enumeration, not the verb; without it, the sentence describes activity and proves nothing about what got through.

go deeper

for a junior

Recall that normalisation deletes a fixed list of things and leaves everything else. Be ready to say why 'we normalise' does not mean 'nothing hidden gets through'.

for a middle

Explain the mechanics: a normalise pass has an enumerable kill-set, so the attacker chooses a carrier outside it, including carriers the pass never even receives on that path.

for a senior

Demonstrate the judgment to reject a 'we normalise' assurance in review and demand the enumerated kept-set, then reason about which kept carrier you would attack first.

for a principal

Own the framing that a control's security value is its stated coverage, not the fact that it runs, and push teams to document what a pass keeps rather than what it does.

## The claim being made When a team says *we normalise input, so hidden characters are gone*, they are stating that a processing step runs. What an interviewer wants to hear is whether the candidate understands that **naming a process is not the same as bounding its coverage.** A *carrier* is whatever an attacker hides a directive span inside so that it reaches the model while a byte-level check or a human skim does not treat it as content: a run of zero-width codepoints between visible letters, a homoglyph that renders like a Latin character but is a different codepoint, text rendered into an image, a caption or alt attribute or title/metadata field on a page that a scraper reads but a person never looks at. The span itself is not the interesting part; **the carrier is.** ## Why normalisation is a set, not a wall A normalising pass is defined by what it targets. A Unicode normalisation form folds certain sequences to a canonical shape. A sanitiser strips a named list of control and zero-width codepoints. A homoglyph mapper folds a table of confusable characters to their Latin base. Each of these is a **specific, enumerable set of removals.** Everything outside the set is untouched, by construction. That is the whole point of the leaf: normalisation removes a specific set and the attacker is choosing from what is left. Concretely, the set a given pass covers might miss: - a homoglyph that is not in its confusables table; - a carrier that is not text at all, such as a directive baked into the pixels of an image, which a text normaliser has no opinion about; - a carrier in a field the normaliser is never handed, because it runs at one pipeline position and a title or metadata field is routed into the prompt around it. ## The two different claims Hold these side by side: | Claim | What it tells a reviewer | |---|---| | "We normalise input." | A pass runs somewhere. Coverage unknown. | | "We remove this codepoint set, and here is the list of carriers we knowingly keep." | Testable. A reviewer can attack each kept carrier. | The second is worth something because it is falsifiable: you can take each carrier it admits to keeping and check whether a span in it reaches the model. The first cannot be attacked or defended because it names no boundary. ## Why this matters in practice Consider a research agent that fetches public web pages nobody vetted and compiles a weekly internal brief. Somewhere in that pipeline is a normalise step, and the team points at it as *coverage*. An attacker does not argue with the step; they read what it removes, and they place their carrier in something it does not: a metadata field the scraper reads before normalisation ever sees it, or an image, or a confusable the table misses. The step ran. It covered nothing on that path. The correct interview answer is therefore not "normalisation is useless" and not "normalisation solves it." It is: **normalisation is a filter with an enumerable kill-set, the security-relevant fact is the set it keeps, and until someone states that set the claim is unverifiable.** A candidate who can articulate the gap between a verb and a coverage list has understood the leaf; one who treats "we normalise" as a guarantee has walked into exactly the wrong answer the topic exists to correct.

  • What single sentence would turn 'we normalise' into a checkable claim?
    Name the exact set the pass removes and, more usefully, the carriers it knowingly keeps: homoglyphs its table misses, text inside images, metadata or title fields it never receives. Once the kept set is written down a reviewer can attack each entry, so the claim becomes falsifiable instead of a description of activity.
  • Why can 'we normalise input' be literally true and still cover nothing on a given path?
    A normaliser runs at one position in the pipeline. A carrier introduced downstream of it, or in a field routed around it, such as a title read straight into the prompt or a directive in an image, is never presented to the pass at all. The step runs on the path it sits on and simply never sees that carrier.

Saying 'we lock the front door' is not the same as listing which doors and windows are locked. The burglar walks the whole perimeter and takes the one you never mentioned.

saying these in an interview costs you the question

  • Claims normalisation strips all invisible or hidden content.
  • Treats 'we normalise' as a guarantee that encoding attacks are impossible.
  • Says a normalise step and an enumerated allowlist of carriers are the same claim.
  • Assumes a text normaliser also handles directives baked into images.

context