Saving a multi-frame image as a PDF takes quadratic time
Pillow: Quadratic-time DoS in PDF save_all (PdfParser.next_object_id)
- Advisory
- CVE-2026-112894
- Library
- Pillow, pillow on PyPI
- Published
- Severity
- not scored upstream
- Affected
- < 12.3.0
- Fixed in
- 12.3.0
- Reaches you
- on a save path
What triggers it
Image.save(format="PDF", save_all=True) of an image with many frames.
What sillybos does
Refused by default
sillybos refuses the triggering file under its default policy, through the max_pages check.
The frame count comes from the opened file: a TIFF's frame chain, which the reader walks, or an animated PNG's acTL count, which it reads. max_pages bounds both, and the default of 500 keeps the quadratic cost small; the 125-byte animated PNG that declares two billion frames is refused on the count alone.
Proposed from the advisory's text on 2026-11-01, as part of folding the backfill into the record; confirmed by a person on 2026-11-03. Re-read on 2026-11-03 against the question of what rides from an opened file into a save: the file is the input.
Proved by these tests in the sillybos suite, each of which builds the triggering file from bytes and checks that it is refused:
tests/test_check.py::TestHostileFiles::test_an_animated_png_that_declares_too_many_framestests/test_check.py::TestHostileFiles::test_a_tiff_with_ten_thousand_frames
How to protect yourself
In general. Upgrade to Pillow 12.3.0.
Specifically. Keep max_pages at what a document needs; sillybos reads the declared frame count before Pillow does.
The general advice applies to every row here.
Sources
- https://osv.dev/vulnerability/GHSA-jg86-v3jv-hrpm
- The record entry, triaged 2026-11-03, last checked 2026-11-03