Text covered by something opaque

pdf.occluded-text

Text drawn normally and then painted over — by a rectangle, a picture, or a gradient — so the reviewer sees the cover and the extractor reads what is underneath.

How the text is hidden

A content stream is ordered, and anything painted after the text lands on top of it. The text operators are untouched: the run has an ordinary colour, an ordinary size and a resolvable background. Structurally it looks visible, which is exactly why nothing short of looking at the page settles it.

Why a model still reads it

The text layer is unmodified by whatever was drawn over it, so extraction returns the covered clause in full.

What we do about it

markCoveredRuns samples a grid across each run's box against fills painted later in the stream (region.seq >= seq), compared against limits.occludingFillMinCoverage; a known-colour fill sets coveredByLaterFill, an unresolvable one — image, shading, non-rectangular path — sets coveredByUnknownFill after being clamped to the page box and tested against limits.occludingUnknownFillMaxPageShare. Neither flag reports anything on its own: both move the page onto the render work-list. The page is then rendered twice, with and without its text layer, and pageAbsence diffs the pixels using limits.minDrawnRatio plus a contiguous-dead-stretch test (limits.partialCoverMinShare, limits.partialCoverMinEm) that an average alone could be diluted past. The rule pdf-occluded-text fires when a run is visible and the render says absentFromRenderhigh, action flag.

How often it fires

8.3% of 400 real UK public-sector contract PDFs (Contracts Finder, 2019–2023) — Word, Adobe, Nitro, office copiers, measured 2026-08-23.

This is an alert-volume number and nothing else. It says how often the alarm sounds on documents as found — not how often it is right, and not whether what it found was harmless. Documents as found may themselves carry concealment. Read it against the population named above rather than as a property of documents in general.

Seen in the wild

7 Jan 2026 · PromptArmor · vendor disclosure
Notion AI: Data Exfiltration

A résumé PDF carried an instruction in 1-point white-on-white text with a white image laid over it, and Notion AI built URLs containing salary expectations and candidate feedback, then embedded them as images so the browser sent them to the attacker.

Every recorded incident, across all techniques.

next

Check your own file

Three commands: a key, credit, a verdict.

Start with the API