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

CVE-2026-59197: Pillow Buffer Overflow Vulnerability

CVE-2026-59197 is a buffer overflow vulnerability in Pillow Python imaging library that triggers a heap out-of-bounds write through rank-filter API. This article covers the technical details, affected versions, and mitigation.

Published:

CVE-2026-59197 Overview

CVE-2026-59197 is a heap out-of-bounds write vulnerability in Pillow, the widely used Python imaging library. The flaw exists in the public rank-filter API prior to version 12.3.0. When ImageFilter.RankFilter.filter() receives a very large odd filter size, it calls image.expand(size // 2, size // 2) before validating the rank-filter size. The underlying ImagingExpand() function then computes output dimensions using unchecked signed integer arithmetic, leading to an integer overflow [CWE-190] and a subsequent native heap out-of-bounds write. The issue is fixed in Pillow 12.3.0.

Critical Impact

Attackers who can influence rank-filter size parameters can trigger memory corruption in native code, causing process crashes and potential integrity impact in applications processing untrusted imaging workflows.

Affected Products

  • Python Pillow imaging library versions prior to 12.3.0
  • Applications embedding Pillow that expose ImageFilter.RankFilter, MedianFilter, MinFilter, or MaxFilter to untrusted input
  • Downstream Python packages and services relying on affected Pillow releases

Discovery Timeline

  • 2026-07-14 - CVE-2026-59197 published to the National Vulnerability Database (NVD)
  • 2026-07-15 - Last updated in NVD database

Technical Details for CVE-2026-59197

Vulnerability Analysis

The vulnerability resides in Pillow's rank-filter implementation. ImageFilter.RankFilter.filter() invokes image.expand(size // 2, size // 2) to add margin pixels before applying the rank filter. Size validation runs after this expansion. When a caller supplies an unusually large odd filter size, the expansion step reaches the native ImagingExpand() routine in src/libImaging/Filter.c, which multiplies the margin and image dimensions using signed 32-bit integer arithmetic. The multiplication wraps around, producing a small or negative allocation size while the write loop uses the attacker-influenced dimensions. This results in an out-of-bounds write on the heap.

Root Cause

The root cause is an integer overflow [CWE-190] in the computation of output image dimensions inside ImagingExpand(), combined with input validation ordering in RankFilter. Filter size checks executed only after the expansion step, so oversized size values reached native code without bounds enforcement.

Attack Vector

Exploitation requires an application that passes attacker-controlled or attacker-influenced parameters to ImageFilter.RankFilter, MedianFilter, MinFilter, or MaxFilter. The vector is network-reachable when such parameters originate from user input in web services, image-processing APIs, or automated pipelines. No authentication or user interaction is required for the vulnerable code path itself.

python
         if size % 2 == 0:
             msg = "bad filter size"
             raise ValueError(msg)
+        if size * size * 4 > (2**31 - 1):
+            msg = "filter size too large"
+            raise ValueError(msg)
         if rank < 0 or rank >= size * size:
             msg = "bad rank value"
             raise ValueError(msg)
# Source: https://github.com/python-pillow/Pillow/commit/cce3bdb867c77a3420261ed1bfdb6b0787ec8fc1
c
     if (margin < 0) {
         return (Imaging)ImagingError_ValueError("bad kernel size");
     }
+    if (margin > INT_MAX / (margin * (int)sizeof(FLOAT32))) {
+        return (Imaging)ImagingError_ValueError("filter size too large");
+    }
 
     imOut =
         ImagingNewDirty(imIn->mode, imIn->xsize + 2 * margin, imIn->ysize + 2 * margin);
// Source: https://github.com/python-pillow/Pillow/commit/cce3bdb867c77a3420261ed1bfdb6b0787ec8fc1

The patch adds bounds checks in both the Python layer (src/PIL/ImageFilter.py) and the native C layer (src/libImaging/Filter.c) before allocation occurs.

Detection Methods for CVE-2026-59197

Indicators of Compromise

  • Python process crashes or segmentation faults involving libImaging or _imaging extension modules
  • Application logs referencing ImagingExpand, RankFilter, MedianFilter, MinFilter, or MaxFilter immediately before abnormal termination
  • Unexpected MemoryError or ValueError exceptions raised from imaging routines after upgrades to 12.3.0

Detection Strategies

  • Inventory installed Python environments and identify Pillow versions below 12.3.0 using pip show pillow or software composition analysis tooling
  • Review application code paths that expose filter size or rank parameters to external inputs, including REST endpoints and background workers
  • Correlate crash telemetry from image-processing services with request payloads containing large numeric filter parameters

Monitoring Recommendations

  • Enable core dump collection and crash reporting for Python workers that use Pillow to detect exploitation attempts
  • Alert on repeated abnormal exits of imaging services and on ValueError patterns containing filter size too large after patching
  • Track dependency updates in CI/CD pipelines to ensure Pillow remains at 12.3.0 or later

How to Mitigate CVE-2026-59197

Immediate Actions Required

  • Upgrade Pillow to version 12.3.0 or later across all environments, including containers, virtual environments, and serverless runtimes
  • Audit application interfaces that accept filter size or rank parameters and enforce strict server-side validation
  • Rebuild and redeploy container images that bundle Pillow to ensure the patched version is loaded at runtime

Patch Information

The fix is available in Pillow 12.3.0. See the GitHub Security Advisory GHSA-xj96-63gp-2gmr, the GitHub Pull Request #9695, the remediation commit cce3bdb, and the Pillow 12.3.0 Release.

Workarounds

  • Reject or clamp user-supplied filter size values in application code so that size * size * 4 never exceeds 2**31 - 1
  • Disable or gate exposure of RankFilter, MedianFilter, MinFilter, and MaxFilter behind trusted administrative interfaces until patching is complete
  • Run image-processing workers under process isolation with resource limits to contain crashes from malformed inputs
bash
# Upgrade Pillow to the patched release
pip install --upgrade "Pillow>=12.3.0"

# Verify the installed version
python -c "import PIL; print(PIL.__version__)"

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

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

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.