Skip to main content
Vulnerability Database/CVE-2026-112897

CVE-2026-112897: Pillow Information Disclosure Vulnerability

CVE-2026-112897 is an information disclosure flaw in Pillow Python imaging library affecting versions 5.3.0 to 13.0.0. Attackers can exploit TIFF decoding to expose uninitialized memory. This article covers technical details, affected versions, impact assessment, and mitigation strategies.

Published:

CVE-2026-112897 Overview

CVE-2026-112897 is an uninitialized memory use vulnerability [CWE-908] in the Pillow Python imaging library. Versions from 5.3.0 up to (but not including) 13.0.0 can return uninitialized heap memory as pixel data when libtiff performs a short decode of JPEG-compressed or Group 4 fax TIFF data. The _decodeStrip and _decodeTile buffers may be larger than the bytes written by libtiff, and Pillow converts the expected rows without clearing the unwritten tail. An attacker who supplies a crafted TIFF to an application that loads and returns or re-encodes its pixels can disclose stale heap contents.

Critical Impact

Remote attackers can leak sensitive process memory contents from any service that decodes attacker-controlled TIFF images using Pillow, without triggering memory corruption or process crashes.

Affected Products

  • Python Pillow tile decode path: versions 5.3.0 through 12.x
  • Python Pillow strip decode path: versions 6.0.0 through 12.x
  • Any Python application or service that calls Image.open() and processes TIFF files with Pillow < 13.0.0

Discovery Timeline

  • 2026-10-19 - CVE-2026-112897 published to the National Vulnerability Database
  • 2026-10-22 - Last updated in NVD database

Technical Details for CVE-2026-112897

Vulnerability Analysis

The flaw resides in src/libImaging/TiffDecode.c, specifically in the strip and tile decode paths that interface with libtiff. Pillow allocates a buffer sized to the full expected tile or strip dimensions. When the underlying libtiff decoder (JPEG or Group 4 fax) succeeds but produces fewer rows than the declared tile length, the trailing region of the buffer is never written. Pillow then unpacks the entire buffer into image pixels, converting the uninitialized tail along with legitimate data.

The affected image is returned, saved, or re-encoded by the host application. The uninitialized bytes can carry residual contents from prior heap allocations, including fragments of secrets, tokens, or other image data processed by the same process.

Root Cause

The root cause is a missing buffer-clear step after realloc() extends the decode buffer. The patch adds a memset() to zero the newly-grown region before libtiff writes to it, ensuring any bytes not populated by a short decode are deterministic zeros rather than stale heap memory.

Attack Vector

The attack is network-reachable and requires no authentication or user interaction. An attacker uploads or submits a malformed TIFF with JPEG or CCITT Group 4 compression where the encoded strip or tile intentionally decodes to fewer rows than its declared length. When a vulnerable server-side application (image processor, thumbnailer, OCR pipeline, document converter) loads the TIFF and returns the resulting PNG, JPEG, or raw pixels, uninitialized memory is exfiltrated inside the output pixels.

c
         return -1;
     }
 
-    state->bytes = tile_bytes_size;
-
     /* realloc to fit whole tile */
     /* malloc check above */
-    new_data = realloc(state->buffer, state->bytes);
+    new_data = realloc(state->buffer, tile_bytes_size);
     if (!new_data) {
         state->errcode = IMAGING_CODEC_MEMORY;
         return -1;
     }
     state->buffer = new_data;
 
+    if (tile_bytes_size > state->bytes) {
+        // Some codecs (e.g. JPEG, Group 4) succeed on a tile that decodes
+        // to fewer rows than the tile length, leaving the rest of the buffer untouched.
+        // Clear it so that uninitialised memory is not copied into the image.
+        memset(state->buffer + state->bytes, 0, tile_bytes_size - state->bytes);
+    }
+
+    state->bytes = tile_bytes_size;
+
     for (y = state->yoff; y < state->ysize; y += tile_length) {
         int plane;
         for (plane = 0; plane < planes; plane++) {

Source: GitHub Pillow Commit 1d4773e

Detection Methods for CVE-2026-112897

Indicators of Compromise

  • Inbound TIFF files with JPEG (Compression=7) or CCITT Group 4 fax (Compression=4) compression where the encoded data decodes to fewer scanlines than declared in the RowsPerStrip or TileLength tags.
  • Output images from server-side pipelines containing high-entropy pixel bands in regions corresponding to undecoded tile or strip tails.
  • Repeated TIFF submissions from the same source to endpoints that return processed images, suggesting automated memory harvesting.

Detection Strategies

  • Inventory Python environments for Pillow versions below 13.0.0 using pip list or SBOM queries across build artifacts and container images.
  • Instrument image-processing services to log TIFF decoder warnings from libtiff indicating short strip or tile reads.
  • Deploy input validation at the application boundary to reject TIFFs whose compressed payload size is inconsistent with declared strip or tile geometry.

Monitoring Recommendations

  • Alert on anomalous volumes of TIFF uploads to endpoints that return re-encoded images, particularly from unauthenticated sources.
  • Monitor outbound responses from image services for repeated requests of identical crafted inputs that yield varying output pixels.
  • Track dependency drift in CI/CD so that Pillow upgrades to 13.0.0+ propagate to all downstream services.

How to Mitigate CVE-2026-112897

Immediate Actions Required

  • Upgrade Pillow to version 13.0.0 or later in all Python environments: pip install --upgrade 'Pillow>=13.0.0'.
  • Rebuild and redeploy container images, Lambda layers, and virtual environments that bundle vulnerable Pillow versions.
  • Audit application code paths that accept TIFF uploads and return or re-encode pixels, prioritizing patching for internet-facing services.

Patch Information

The fix is published in Pillow Release 13.0.0 and tracked in GHSA-q45j-58j2-45rg. The patch commit 1d4773e adds a memset() call in TiffDecode.c to zero the extended portion of the strip and tile buffers before libtiff writes decoded pixel data.

Workarounds

  • Reject TIFF uploads at the application layer where the format is not required, restricting accepted MIME types to formats such as PNG and JPEG.
  • Decode untrusted TIFFs inside short-lived sandboxed processes with minimal address-space contents to reduce the value of any leaked memory.
  • Pre-validate TIFF structure with a hardened parser and refuse files whose JPEG or Group 4 compressed payloads do not match declared strip or tile row counts.
bash
# Verify installed Pillow version and upgrade if vulnerable
python -c "import PIL; print(PIL.__version__)"
pip install --upgrade 'Pillow>=13.0.0'

# Audit a requirements file for vulnerable pins
grep -Ei '^(pillow|PIL)[=<>]' requirements.txt

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.