CVE-2026-40192 Overview
CVE-2026-40192 is a resource exhaustion vulnerability in Pillow, the popular Python imaging library. Versions 10.3.0 through 12.1.1 failed to limit the amount of GZIP-compressed data read when decoding FITS (Flexible Image Transport System) image files, making them susceptible to decompression bomb attacks. An attacker can craft a malicious FITS file that, when processed by Pillow, causes unbounded memory consumption resulting in denial of service through an out-of-memory crash or severe performance degradation.
Critical Impact
Processing a specially crafted FITS image file can cause complete denial of service through memory exhaustion, potentially crashing applications and services that process user-supplied images using Pillow.
Affected Products
- Pillow versions 10.3.0 through 12.1.1
- Python applications using Pillow for FITS image processing
- Web applications and services accepting user-uploaded FITS images
Discovery Timeline
- April 15, 2026 - CVE CVE-2026-40192 published to NVD
- April 15, 2026 - Last updated in NVD database
Technical Details for CVE-2026-40192
Vulnerability Analysis
This vulnerability is classified as CWE-400 (Uncontrolled Resource Consumption). The flaw exists in Pillow's FITS image decoder, specifically in the FitsImagePlugin.py module. When processing GZIP-compressed FITS images, the vulnerable code path decompresses the entire compressed stream into memory without any size limits. This design flaw allows an attacker to craft a small compressed file that expands to an enormous size when decompressed, overwhelming system memory.
The vulnerability is network-exploitable since FITS images are commonly uploaded to web applications and image processing services. No authentication or user interaction is required to trigger the vulnerability—simply submitting a malicious FITS file to a vulnerable application is sufficient.
Root Cause
The root cause lies in the decode method of the FITS image decoder. The original implementation called gzip.decompress(self.fd.read()), which reads and decompresses the entire GZIP stream without bounds checking. This allows a small compressed payload to expand to gigabytes of data, exceeding available memory and causing denial of service.
Attack Vector
An attacker can exploit this vulnerability by submitting a specially crafted FITS file to any application using vulnerable Pillow versions for image processing. The attack requires no authentication and works via network delivery. Typical attack scenarios include:
- Uploading a malicious FITS image to a web application that processes user images
- Sending a FITS file as an email attachment to trigger processing by an automated system
- Hosting a malicious FITS file that gets fetched and processed by a vulnerable crawler or service
Security Patch (src/PIL/FitsImagePlugin.py):
def decode(self, buffer: bytes | Image.SupportsArrayInterface) -> tuple[int, int]:
assert self.fd is not None
- value = gzip.decompress(self.fd.read())
-
- rows = []
- offset = 0
- number_of_bits = min(self.args[0] // 8, 4)
- for y in range(self.state.ysize):
- row = bytearray()
- for x in range(self.state.xsize):
- row += value[offset + (4 - number_of_bits) : offset + 4]
- offset += 4
- rows.append(row)
+ with gzip.open(self.fd) as fp:
+ value = fp.read(self.state.xsize * self.state.ysize * 4)
+
+ rows = []
+ offset = 0
+ number_of_bits = min(self.args[0] // 8, 4)
+ for y in range(self.state.ysize):
+ row = bytearray()
+ for x in range(self.state.xsize):
+ row += value[offset + (4 - number_of_bits) : offset + 4]
+ offset += 4
+ rows.append(row)
self.set_as_raw(bytes([pixel for row in rows[::-1] for pixel in row])
return -1, 0
Source: GitHub Commit Reference
The fix replaces unbounded decompression with a bounded read that only extracts the exact amount of data needed based on image dimensions (self.state.xsize * self.state.ysize * 4), preventing decompression bombs from consuming excessive memory.
Detection Methods for CVE-2026-40192
Indicators of Compromise
- Sudden spikes in memory consumption on servers processing image uploads
- Application crashes with out-of-memory errors during FITS file processing
- Unusually small FITS files (high compression ratio) in upload queues or logs
- Process terminations with OOM killer events in system logs
Detection Strategies
- Monitor memory usage patterns for image processing services and set alerts for anomalous consumption
- Implement file type validation that checks FITS file headers before processing
- Deploy application-level logging to track FITS image processing operations
- Use dependency scanning tools to identify Pillow versions 10.3.0 through 12.1.1 in your codebase
Monitoring Recommendations
- Configure memory limits and resource quotas for image processing containers and services
- Implement health checks that detect memory exhaustion conditions
- Set up automated alerts for Python application crashes related to memory errors
- Monitor system logs for OOM killer activity targeting Pillow-dependent services
How to Mitigate CVE-2026-40192
Immediate Actions Required
- Upgrade Pillow to version 12.2.0 or later immediately
- Audit all applications and services that process user-supplied images for vulnerable Pillow versions
- Implement input validation to reject or quarantine FITS files until patching is complete
- Configure memory limits for image processing workers to contain potential impact
Patch Information
The vulnerability is fixed in Pillow version 12.2.0. The patch modifies the FITS decoder to read only the required amount of decompressed data based on image dimensions, preventing unbounded memory consumption. For detailed patch information, see the GitHub Pull Request and Pillow Release Notes.
Additional technical details are available in the GitHub Security Advisory.
Workarounds
- Restrict image processing to specific formats excluding FITS until upgrade is possible
- Implement a whitelist of allowed image formats: Image.open(fp, formats=["PNG", "JPEG", "GIF"])
- Deploy resource limits (memory cgroups, container limits) to contain denial of service impact
- Pre-validate uploaded files and reject FITS format until patched
# Configuration example - Upgrade Pillow to patched version
pip install --upgrade "Pillow>=12.2.0"
# Verify 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.

