Jul 21, 2026·5 min read·7 visits
Unbounded zlib decompression in Pillow's PDF parser allows remote attackers to cause system Out-of-Memory crashes using crafted PDF files.
CVE-2026-59200 is a high-severity uncontrolled resource consumption vulnerability in the Pillow Python Imaging Library. The flaw resides in the PDF stream decoder, allowing remote, unauthenticated attackers to trigger host out-of-memory crashes by submitting malicious PDF decompression bombs.
Pillow is a widely adopted Python Imaging Library that handles graphic metadata parsing and image manipulation. Within its PDF handling routines, specifically inside the PDF stream decoder implemented in PdfParser.PdfStream.decode() in PIL/PdfParser.py, the library provides capability for decompressing binary vector data blocks.
The vulnerability is classified as an uncontrolled resource consumption flaw, mapping to CWE-400 and CWE-770, commonly referred to as a decompression bomb. Because decompression routines are processed synchronously upon parsing complex file formats, this flaw exposes a significant remote attack surface.
Any application utilizing Pillow to automatically process untrusted PDF uploads, generate thumbnails, or inspect image metadata is susceptible. The vulnerability does not require authentication or user interaction to trigger, making it an effective vector for targeting downstream processing daemons.
The underlying bug stems from an architectural misunderstanding of Python's standard zlib.decompress(data, bufsize) function. When the PDF stream parser encounters a /FlateDecode filter, it reads the /Length or /DL properties defined within the PDF dictionary wrapper to determine the expected decompressed stream length.
The developer assumed that specifying bufsize=int(expected_length) would act as a security limit, preventing Python's zlib wrapper from returning output that exceeds the specified length. In reality, Python's implementation uses the bufsize parameter solely as an initial memory buffer allocation hint to optimize execution, not as a maximum boundary limit.
When a zlib stream is parsed, if the actual uncompressed payload exceeds this initial size hint, the underlying C-native implementation automatically grows the allocation buffer dynamically. An attacker can construct a payload consisting of highly repetitive bytes (e.g., recursive null blocks) that compress highly efficiently but expand into gigabytes. This leads to unbounded memory allocation on the heap, triggering immediate host resource exhaustion and operating system kernel-level OOM (Out-Of-Memory) process termination.
The vulnerable code path inside PIL/PdfParser.py relied on direct execution of zlib.decompress using the untrusted length header:
# Vulnerable Implementation (< 12.3.0)
def decode(self) -> bytes:
try:
filter = self.dictionary[b"Filter"]
except KeyError:
return self.buf
if filter == b"FlateDecode":
try:
expected_length = self.dictionary[b"DL"]
except KeyError:
expected_length = self.dictionary[b"Length"]
# The bufsize parameter only acts as an allocation hint
return zlib.decompress(self.buf, bufsize=int(expected_length))The patched version replaces this logical block, introducing a secure streaming decompressor instantiation via zlib.decompressobj(). The patch implements validation using ImageFile.SAFEBLOCK as a hard limit:
# Patched Implementation (>= 12.3.0)
def decode(self, max_length: int = ImageFile.SAFEBLOCK) -> bytes:
try:
filter = self.dictionary[b"Filter"]
except KeyError:
return self.buf
if filter == b"FlateDecode":
# Use secure streaming object decompressor
dobj = zlib.decompressobj()
plaintext = dobj.decompress(self.buf, max_length)
# If there are unconsumed input bytes remaining, size exceeded the threshold
if dobj.unconsumed_tail:
msg = "Decompressed data too large"
raise ValueError(msg)
return plaintextBy leveraging dobj.unconsumed_tail, the parser validates if there is remaining compressed content that was not inflated because the max_length restriction was hit. If present, the routine immediately aborts, raising a ValueError prior to the allocation of additional system memory.
To exploit this vulnerability, an attacker constructs a PDF document containing a compressed stream object. The stream's content represents a high-expansion compression bomb utilizing standard DEFLATE compression.
The attacker structures the stream object with a /Length tag matched to the small compressed size to evade simple perimeter length checks. Once submitted to the target application, the backend parses the file and initiates decompression via the vulnerable PdfStream.decode() method.
Because the Python process executes this decompression step synchronously inside a native C module, the application is unable to interdict or limit the allocation once execution has been handed off to the standard library. The process continues to claim resources until terminated by the operating system kernel.
The impact of CVE-2026-59200 is restricted to availability, yielding a High score under the CVSS metric. Execution of the exploit results in an immediate Out-of-Memory event on the target host processing the file.
In standard enterprise environments, this triggers the OS kernel OOM-killer to terminate the application's daemon worker process (e.g., Gunicorn worker, Celery runner, or uWSGI process). This leads to localized Denial of Service for active connections and processing queues.
While this vulnerability does not yield remote code execution or data exposure, it represents a highly stable vector for disrupting service availability. Because the attack requires no privileges, any public-facing upload portal utilizing vulnerable parser modules is exposed to disruption.
The primary remediation path is upgrading the local Pillow dependency to version 12.3.0 or higher, which contains the official patch. This replaces the insecure decompress path with the streaming verification logic.
Where upgrading is not immediately feasible, you can apply workarounds at the application level. Ensure that applications restrict processed file types by explicitly defining safe formats within Image.open instead of utilizing default format detection.
# Safe application entry-point handling
SAFE_FORMATS = ["PNG", "JPEG", "WEBP"]
try:
im = Image.open(user_file, formats=SAFE_FORMATS)
im.verify()
except Exception as e:
raise ValueError("Unsupported format requested")Additionally, restrict operational resources at the operating system or containerization level. By establishing strict memory constraints on individual daemon processes, you can prevent a single payload execution from exhausting the entire virtual host resource pool.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Attribute | Detail |
|---|---|
| CWE ID | CWE-400 |
| Attack Vector | Network |
| CVSS | 7.5 |
| EPSS Score | 0.0035 |
| Impact | High (Denial of Service) |
| Exploit Status | Proof-of-Concept Available |
| KEV Status | Not Listed |
The software does not properly control the allocation of memory during decompression, enabling remote attackers to exhaust host RAM.
CVE-2026-50525 is a high-severity Denial of Service (DoS) vulnerability in the Microsoft .NET XML Cryptography stack. The vulnerability resides in the `System.Security.Cryptography.Xml` library, specifically within the `EncryptedXml` processing engine. Unauthenticated remote attackers can exploit this flaw by sending specifically crafted XML documents containing nested or recursive structures, or utilizing resource-intensive transforms. Processing such payloads leads to infinite CPU loops, stack exhaustion, or memory starvation, resulting in application termination.
An improper encoding and escaping vulnerability in the .NET SMTP client component allows network-based attackers to perform SMTP command smuggling and email spoofing by injecting control characters into email fields.
CVE-2026-50651 is a high-severity Denial of Service vulnerability in Microsoft .NET runtimes, SDKs, and Visual Studio installations. It stems from a weakness in System.Net.Http (CWE-770), where the HTTP/2 connection handling state machine fails to throttle server-initiated protocol streams and control frames. An attacker-controlled server can exploit this by returning highly fragmented or infinite control and continuation frame sequences. This forces the client to allocate memory indefinitely on the managed heap, eventually provoking an unhandled Out-of-Memory (OOM) exception and application crash.
A heap out-of-bounds write vulnerability exists in Pillow prior to version 12.3.0 due to an integer overflow during image expansion calculations. The subsequent patch introduced a division-by-zero regression causing denial of service.
CVE-2026-59198 is a high-severity heap out-of-bounds read vulnerability in Pillow, the Python imaging library, affecting versions from 5.2.0 up to 12.3.0. The vulnerability occurs in the TGA RLE compression path due to a calculation mismatch between the allocated packed 1-bit row buffer and the byte-level pixel stride assumption in the C-level encoder. This mismatch allows an attacker to leak up to approximately 57 KB of adjacent process heap memory directly into generated TGA image files.
A critical signed 32-bit integer overflow vulnerability was identified in Pillow (Python Imaging Library) versions prior to 12.3.0. The vulnerability resides within the native C extension library (libImaging) during coordinate and bounding box calculations in functions like ImagingPaste and ImagingFill2. Exploitation can bypass bounds and clipping safety checks, leading to a controlled heap backward underwrite and application crash.