Advisory Database
  • Advisories
  • Dependency Scanning
  1. pypi
  2. ›
  3. Pillow
  4. ›
  5. CVE-2026-112894

CVE-2026-112894: Pillow: Quadratic-time DoS in PDF save_all (PdfParser.next_object_id)

October 21, 2026

============================================================================
Quadratic-time DoS in PDF save_all (PdfParser.next_object_id)
Location: src/PIL/PdfParser.py:629  in next_object_id()
Commit:   a707c6b21c313880d0771e54965d142dd42358b6
============================================================================

Pillow’s PDF writer takes time proportional to the square of the number of frames when it saves a multi-frame image as a multi-page PDF. Anyone who can get an application to convert their uploaded image this way can tie up a worker at full CPU for minutes with a small file. A 240 KB animated image takes about 70 seconds, a 720 KB one an estimated 10 minutes, and a 125-byte animated PNG that merely declares a large frame count triggers the same slowdown with no upper bound short of 2³¹ frames. Memory stays under 100 MB and the decompression-bomb limit never applies.

The cause is PdfParser.next_object_id() in src/PIL/PdfParser.py, which finds the next free id by computing max(self.xref_table.keys()). XrefTable.keys() rebuilds three sets over every id reserved so far on each call. PdfImagePlugin._save() calls it three times (four for palette images with transparency) per frame, for n_frames frames, before any page is written. That makes the id-reservation loop alone O(N²). Because n_frames is taken from the file before any frame is seeked, APNG’s acTL count drives the loop even when the frames don’t exist. In that case the save raises OSError only after the full delay.

The precondition is that the application calls im.save(..., "PDF", save_all=True) on the attacker’s file; Image.open() and load() alone do not reach this code. The attached reproducer shows 4× the frames costing about 11× the CPU for a valid GIF and about 16× for a fixed 125-byte APNG. The behaviour was introduced in 6207b44ab1ff (2018-01-18) and first shipped in Pillow 5.1.0. A small patch that tracks the highest id in XrefTable makes the save linear.

References

  • github.com/advisories/GHSA-jg86-v3jv-hrpm
  • github.com/python-pillow/Pillow/commit/f6a852555f1a1bdff7781abf25f1a3b8bd6ce6cb
  • github.com/python-pillow/Pillow/releases/tag/13.0.0
  • github.com/python-pillow/Pillow/security/advisories/GHSA-jg86-v3jv-hrpm
  • nvd.nist.gov/vuln/detail/CVE-2026-112894

Code Behaviors & Features

Detect and mitigate CVE-2026-112894 with GitLab Dependency Scanning

Secure your software supply chain by verifying that all open source dependencies used in your projects contain no disclosed vulnerabilities. Dependency Scanning using SBOM also detects vulnerabilities from proprietary advisories that this site does not include. Learn more about Dependency Scanning using SBOM →

Affected versions

All versions starting from 5.1.0 before 13.0.0

Fixed versions

  • 13.0.0

Solution

Upgrade to version 13.0.0 or above.

Impact 7.5 HIGH

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Learn more about CVSS

Weakness

  • CWE-407: Inefficient Algorithmic Complexity

Source file

pypi/Pillow/CVE-2026-112894.yml

Spotted a mistake? Edit the file on GitLab.

  • Site Repo
  • About GitLab
  • Terms
  • Privacy Statement
  • Contact

Page generated Sun, 08 Nov 2026 00:17:13 +0000.