Tetrak
GitHub ↗
Security · Pillow

A lossless JPEG overruns the decode buffer when scaled

Heap buffer overflow in ImagingJpegDecode: a lossless (SOF3) frame ignores the requested scaling and writes full-width rows into a buffer sized for the scaled width.

Advisory
CVE-2026-112403 (also GHSA-8g5g-8vmr-9782)
Library
Pillow, pillow on PyPI
Published
Severity
9.2 out of 10, as published
Affected
<= 12.3.0
Fixed in
13.0.0
Reaches you
by opening a file

What triggers it

A standards-compliant lossless JPEG, opened and then drafted or thumbnailed (Image.thumbnail() does this on its own). The advisory notes that formats=["JPEG"] does not prevent it.

What sillybos does

Refused by default

sillybos refuses the triggering file under its default policy, through the jpeg_frames check.

The frame coding is read from the JPEG's frame header. The default policy allows baseline, extended and progressive frames only; a lossless frame is refused with the coding named.

Proved by this test in the sillybos suite, which builds the triggering file from bytes and checks that it is refused:

How to protect yourself

In general. Upgrade to Pillow 13.0.0. Call load() before thumbnail(), or pass reducing_gap=None, until then.

Specifically. Refuse frame codings a scanner never writes: lossless, hierarchical, arithmetic. sillybos does this by default.

The general advice applies to every row here.

Sources