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

CVE-2026-112897: Pillow: TiffDecode returns uninitialized memory as pixels for short JPEG strips

October 20, 2026

============================================================================
TiffDecode returns uninitialized memory as pixels for short JPEG strips
Location: src/libImaging/TiffDecode.c:554  in _decodeStrip()
Commit:   a707c6b21c313880d0771e54965d142dd42358b6
============================================================================

Pillow hands back leftover process memory as image pixels when it opens a small crafted TIFF file. Anyone who can get an application to open their image, and can see something produced from its pixels (a thumbnail, a preview, a converted copy), can read heap memory that the process had previously used and freed. This works in the default configuration: opening and loading the 478-byte file succeeds with no error or warning, and every row below the first eight holds stale memory instead of picture content.

The bug is in _decodeStrip() in src/libImaging/TiffDecode.c, and _decodeTile() has the same shape. The function realloc()s state->buffer to TIFFStripSize() bytes without initialising it and calls TIFFReadEncodedStrip(). Whenever that call does not return -1, it copies all RowsPerStrip rows of the buffer into the image. libtiff’s JPEG codec only warns when the JPEG embedded in a strip has fewer rows than the strip, and Pillow silences libtiff warnings. The codec decodes the rows that exist and still returns the full strip size, so the untouched remainder is copied out as pixels. libtiff’s Group 4 fax codec behaves the same way for a stream that ends early.

The attached reproducer builds a 256×256 TIFF whose single strip or tile is a 256×8 JPEG. Before loading it, the script frees buffers filled with b"LEAK". It then finds 15,872 copies of LEAK in rows 8–255 of the decoded image (the same freed chunk was reused in 500 of 500 runs). Under glibc’s MALLOC_PERTURB_, those rows are entirely the allocator’s fill byte. A well-formed control file decodes correctly in both cases.

This is a read of uninitialised heap memory, not memory corruption. Each strip can disclose up to width × RowsPerStrip bytes, and what comes back depends on the allocator’s state at the time. The strip path was introduced in e91b851fdc1c (“Add reading old-JPEG compressed TIFFs”, first released in Pillow 6.0.0). The tile path has had the same pattern since f0436a4ddc95 (Pillow 5.3.0).

References

  • github.com/advisories/GHSA-q45j-58j2-45rg
  • github.com/python-pillow/Pillow/commit/1d4773e6cea0c4a2814e6d4cdc099bbcf56da6ce
  • github.com/python-pillow/Pillow/releases/tag/13.0.0
  • github.com/python-pillow/Pillow/security/advisories/GHSA-q45j-58j2-45rg
  • nvd.nist.gov/vuln/detail/CVE-2026-112897

Code Behaviors & Features

Detect and mitigate CVE-2026-112897 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.3.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:H/I:N/A:N

Learn more about CVSS

Weakness

  • CWE-908: Use of Uninitialized Resource

Source file

pypi/Pillow/CVE-2026-112897.yml

Spotted a mistake? Edit the file on GitLab.

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

Page generated Wed, 21 Oct 2026 12:16:44 +0000.