
CVE-2026-74945, Uninitialized heap disclosure via a crafted web font (sec-high)
This directory holds an honest reproduction package for an uninitialized-memory
disclosure in Firefox font handling. A crafted @font-face font walks the OTS
output stream into an uninitialized-heap gap, and ordinary content reads bytes of
that gap back through the canvas measureText API. It is meant to be run against
a locally downloaded vulnerable Firefox build with synthetic data only. It
never touches any live or third party system.
Matching PoC repository: https://github.com/defineid/Palimpsest
Writeup: writeup-font-cmap-leak.html in this portfolio.
| Field | Value |
|---|
| CVE | CVE-2026-74945 |
| Component | Core / Graphics: Text |
| Class | Uninitialized Memory Disclosure (CWE-908 · CWE-200) |
| Severity | sec-high (web-reachable memory disclosure) |
| Fixed in | Firefox 154 · ESR 140.14 |
| Bug | bugzilla.mozilla.org/show_bug.cgi?id=2057808 |
| Interaction | None · page load only |
Firefox sanitizes web fonts through OTS before use. Three independent defects line up so that a crafted font leaves an uninitialized-heap gap inside the sanitized output and content can read it back:
moz_xrealloc) that does not zero-fill new space.cmap format-14 subtable with a
large nonDefaultUVSOffset makes OTS seek its output stream forward when it
re-serializes the sanitized font. The skipped span between the written bytes
and the seek target is handed to the caller carrying uninitialized heap, and
forget() sizes the buffer to the highest offset reached.cmap table rather than the
subtable, so a segment whose idRangeOffset runs off the end of the format-4
data still passes the check and reads into the neighbouring subtable's
uninitialized bytes.The crafted font pairs a format-4 subtable, whose last segment (0xFFFF) uses an
odd, overrunning idRangeOffset, with a format-14 subtable carrying a large
nonDefaultUVSOffset, plus maxp.numGlyphs = 65535 and a distinct hmtx
advance per glyph id (advance == glyph id). Measuring U+FFFF therefore resolves
to a glyph id read from the uninitialized gap, and its advance width, readable
from script, discloses about two bytes of heap per measurement over a roughly
64 KB window.
An ordinary web page serves the crafted font through @font-face and calls
ctx.measureText(""). No click, permission, extension, or pref change is
required. OTS runs in-process and is not among the sandboxed libraries, so the
disclosed bytes are content-process heap that may contain pointers or secrets.
| File | Purpose |
|---|---|
make_font.py | Builds leak.otf and leak.woff, the crafted fonts. |
trigger.html | Bare page that @font-face-loads the font and reads the U+FFFF advance back through measureText. |
https://ftp.mozilla.org/pub/firefox/releases/140.9.0esr/.pip install fonttools brotli
python3 make_font.py # writes leak.otf and leak.woff in this directory
Then open trigger.html in the vulnerable build, from a file:// path or a
local static server you control, and click Measure.
.notdef) and the advance is 0. No gap is leaked, because the output stream
is zeroed and the format-4 lookup is bounded to its own subtable.make_font.py was executed here with fontTools
4.63.0 and produced leak.otf (393816 bytes) and leak.woff (132372 bytes).
The generated font was parsed back from raw bytes and every crafted ingredient
was confirmed: maxp.numGlyphs = 65535, hhea.numberOfHMetrics = 65535, a
distinct hmtx advance per glyph id (advance == glyph id), two cmap
subtables (platform 3 encoding 1 format 4, and platform 0 encoding 5 format
14), the format-4 last segment endCode = 0xFFFF with an odd overrunning
idRangeOffset = 0x4001, and the format-14 nonDefaultUVSOffset = 0x8000.trigger.html yourself against a local vulnerable build to observe the leak.
This package demonstrates the crafted input and the read-back path; it is not a
weaponized exploit and includes no controlled code-execution primitive.This targets a locally downloaded build with synthetic, self-generated font data, for a writeup of the author's own reported and already patched CVE. It does not attack any live or third party service.