CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-59198

CVE-2026-59198: Heap Out-of-Bounds Read in Pillow TGA RLE Encoder

Alon Barad
Alon Barad
Software Engineer

Jul 21, 2026·8 min read·3 visits

Executive Summary (TL;DR)

A calculation mismatch in Pillow's TGA RLE encoder allows remote attackers to leak up to 57 KB of process heap memory by saving 1-bit images with RLE compression.

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.

Vulnerability Overview

The affected component is Pillow's TGA (Truevision Graphics Adapter) image plugin, which manages decoding and encoding operations for TGA-formatted files. Specifically, the vulnerability resides within the Run-Length Encoded (RLE) compression routine. Under standard conditions, applications invoke Pillow to process, transform, and export images, exposing the internal C-based codec libraries to user-supplied input parameters.

The TGA format supports multiple image modes, including 1-bit monochrome (represented as mode "1" in Pillow). When an application saves a mode "1" image using TGA format and specifies RLE compression, control flows from the Python wrapper src/PIL/TgaImagePlugin.py down to the underlying C-extension layer located in src/libImaging/TgaRleEncode.c via the encode.c interface.

The attack surface exists in any application workflow where user-supplied or user-controlled images are saved as TGA files with RLE compression enabled. Since the library fails to validate the compatibility of the bit-packed representation of mode "1" images with the byte-stride assumptions of the RLE encoder, memory layout discrepancies occur during serialization. This leads to a heap-based out-of-bounds read vulnerability, which serializes adjacent process memory directly into the generated output file.

Root Cause Analysis

The root cause of CVE-2026-59198 is a mathematical discrepancy between how Pillow structures bit-packed 1-bit monochrome images in memory and how the TGA RLE encoder reads individual pixel values. In a mode "1" image, Pillow packs 8 monochrome pixels into a single byte of memory to optimize storage efficiency. The initial row buffer allocation size is computed in the C-level encoding controller using the calculation Allocation Size = ((state->bits * state->xsize) + 7) / 8.

When saving a TGA image with a maximum width of 65,535 pixels, the allocation formula evaluates to ((1 * 65535) + 7) / 8 = 8192 bytes. This represents the precise buffer size allocated on the heap to contain the packed 1-bit image data.

However, when RLE compression is enabled, execution transitions to ImagingTgaRleEncode within src/libImaging/TgaRleEncode.c. To iterate through the pixels, the encoder calculates the individual pixel stride using the formula bytesPerPixel = ((state->bits + 7) / 8). Because state->bits is 1 for mode "1" images, integer division rounds this calculation up to 1. Consequently, the encoder assumes that each pixel occupies a full byte rather than a single bit. During iteration, the encoder walks the buffer using an offset of x * bytesPerPixel where x runs up to the full image width of 65,535. This causes the encoder to read up to 65,535 bytes from an 8,192-byte buffer, leading to an out-of-bounds read of approximately 57,343 bytes of adjacent heap memory.

Code Analysis

To understand the flaw and the subsequent correction, examine the vulnerable logical path in the TGA saving routine. The following diagram illustrates the workflow leading to the out-of-bounds read:

The implementation patch blocks the vulnerability at the Python interface level in src/PIL/TgaImagePlugin.py. The patch intercepts the execution path prior to reaching the vulnerable C-extension layer by raising an OSError if a mode "1" image is saved with TGA RLE compression.

Below is the comparison of the vulnerable Python wrapper code versus the patched version:

# === VULNERABLE CODE (Pre-Patch) ===
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
    # ... configuration and header parsing ...
    compression = im.encoderinfo.get("compression", im.info.get("compression"))
    rle = compression == "tga_rle"
    if rle:
        imagetype += 8 # Execution proceeds to C-level RLE encoder with packed bit-buffer
 
# === PATCHED CODE (Post-Patch) ===
def _save(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
    # ... configuration and header parsing ...
    compression = im.encoderinfo.get("compression", im.info.get("compression"))
    rle = compression == "tga_rle"
    if rle:
        if im.mode == "1":
            # Prevent the creation of incompatible modes with C-level RLE encoder
            msg = f"cannot write mode {im.mode} as TGA with run-length encoding"
            raise OSError(msg)
 
        imagetype += 8

While this wrapper-level validation successfully prevents exploitation via standard Pillow APIs, it is technically an indirect mitigation. The underlying C function ImagingTgaRleEncode remains unaltered. If external extensions bypass the Python plugin layer and interact directly with the C API using custom packed structures, the underlying memory access discrepancy may still occur. Developers using custom C wrappers for Pillow components must verify that packed images are normalized to 8-bit representation prior to invoking TGA compression.

Exploitation Methodology

Exploiting CVE-2026-59198 does not require specialized authentication or local privileges but is constrained by the application's implementation details. The threat actor must target an application that exposes image uploading and conversion services, allowing the user to dictate the output file format or force TGA RLE processing. The system must also process binary or monochrome images (mode "1") without automatic color-space translation.

An attack scenario proceeds through the following sequential steps:

  1. The attacker uploads a custom-crafted 1-bit monochrome image or forces an existing image to be converted to mode "1".
  2. The attacker triggers the export routine using TGA format with RLE compression enabled (compression="tga_rle").
  3. The backend allocates an 8,192-byte packed buffer for the image row data but invokes the C-level TGA RLE encoder, which processes the memory as if it were 65,535 bytes wide.
  4. The encoder reads approximately 57 KB of memory beyond the allocated row buffer. Since these out-of-bounds bytes are processed by the run-length encoder, they are serialized and written directly into the compressed output data stream of the resulting TGA file.
  5. The attacker downloads the generated TGA image and extracts the raw, uncompressed payload, which contains adjacent process heap memory.

The vulnerability behaves reliably because the C encoder uses deterministic loop bounds. The primary limitation to exploitation is the memory layout adjacent to the image row buffer. If the adjacent memory is unmapped or falls outside the process space, the read will trigger a segmentation fault, causing a denial of service. If the adjacent memory contains active heap data, the data is successfully exfiltrated in the exported file.

Impact Assessment & Threat Intelligence

The primary security consequence of CVE-2026-59198 is unauthorized information disclosure via heap memory exfiltration. Because the heap stores temporary variables, configuration parameters, and buffers from other active application threads, the leaked 57 KB of data may contain sensitive credentials, active session tokens, application keys, or database records. In multi-tenant environments, this leakage could allow one user to intercept the transaction details or credentials of another user processing data concurrently.

Additionally, the leak of heap pointers and internal structural references can bypass Address Space Layout Randomization (ASLR). This provides attackers with the necessary memory layout details to construct subsequent memory corruption exploits. The CVSS v3.1 vector is rated as CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:L with a base score of 6.5. The attack complexity is rated high because it depends on the target application executing a specific image processing flow with specific format parameters.

According to the Exploit Prediction Scoring System (EPSS), the probability of active exploitation in the wild remains low at 0.31% (percentile 23.42%). The vulnerability is not listed in CISA's Known Exploited Vulnerabilities (KEV) catalog, and there are no reports of active exploitation in ransomware campaigns. The overall exploit maturity is limited to proof-of-concept testing.

Remediation & Defensive Guidance

The recommended remediation strategy is upgrading the Pillow installation to version 12.3.0 or higher. This version implements strict input verification at the wrapper layer, raising an OSError and preventing execution from reaching the vulnerable C-based TGA RLE encoder.

In scenarios where immediate package upgrades are unfeasible due to dependency pinning or production freeze windows, developers must implement application-level input sanitization. The following code snippet demonstrates how to intercept and reject vulnerable configurations before saving:

def secure_save(image, output_path, **kwargs):
    # Replicate the patch logic to block the vulnerable path
    format_type = kwargs.get("format", "").upper()
    compression_type = kwargs.get("compression", "")
    
    if format_type == "TGA" and compression_type == "tga_rle":
        if image.mode == "1":
            raise ValueError("Incompatible saving configuration blocked to prevent security risks")
    
    image.save(output_path, **kwargs)

Additionally, security teams should adhere to sandboxing principles for high-risk parsing code. Executing image processing operations within temporary, short-lived containers or restricted namespaces limits the impact of potential information leaks. Restricting the list of permitted image formats and modes via white-lists during file ingest also significantly reduces the available attack surface.

Official Patches

python-pillowOfficial patch removing support for TGA RLE with mode 1 images

Fix Analysis (1)

Technical Appendix

CVSS Score
6.5/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:L
EPSS Probability
0.31%
Top 77% most exploited

Affected Systems

Pillow (Python Imaging Library)

Affected Versions Detail

Product
Affected Versions
Fixed Version
Pillow
python-pillow
>= 5.2.0, < 12.3.012.3.0
AttributeDetail
CWE IDCWE-125
Attack VectorNetwork
CVSS v3.16.5 (Medium)
EPSS Score0.00313
ImpactInformation Disclosure (Heap Leak up to ~57 KB)
Exploit StatusProof-of-Concept
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1005Data from Local System
Collection
CWE-125
Out-of-bounds Read

The software reads data past the end, or before the beginning, of the intended buffer.

Vulnerability Timeline

Mitigation commit merged into upstream repository
2026-06-22
CVE-2026-59198 officially published and disclosed
2026-07-14
Pillow version 12.3.0 released containing the official patch
2026-07-14

References & Sources

  • [1]Pillow GitHub Security Advisory
  • [2]GitHub Pull Request #9709
  • [3]Official Patch Commit
  • [4]Pillow v12.3.0 Release Notes
  • [5]NVD Vulnerability Details
  • [6]CVE.org Official Record

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•10 minutes ago•CVE-2026-50525
7.5

CVE-2026-50525: Denial of Service Vulnerability in Microsoft .NET XML Cryptography Stack

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.

Amit Schendel
Amit Schendel
0 views•6 min read
•about 1 hour ago•CVE-2026-50659
6.5

CVE-2026-50659: SMTP Command and Header Injection in .NET System.Net.Mail

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.

Alon Barad
Alon Barad
1 views•8 min read
•about 2 hours ago•CVE-2026-50651
7.5

CVE-2026-50651: Denial of Service via Uncontrolled Resource Allocation in .NET System.Net.Http

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.

Amit Schendel
Amit Schendel
4 views•6 min read
•about 3 hours ago•CVE-2026-59197
8.2

CVE-2026-59197: Heap Out-of-Bounds Write and Division-by-Zero in Pillow libImaging

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.

Alon Barad
Alon Barad
3 views•3 min read
•about 5 hours ago•CVE-2026-59199
7.5

CVE-2026-59199: Signed 32-Bit Integer Overflow and Heap Backward Underwrite in Pillow

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.

Alon Barad
Alon Barad
7 views•6 min read
•about 6 hours ago•CVE-2026-59200
7.5

CVE-2026-59200: Remote Denial of Service via PDF Decompression Bomb in Pillow

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.

Alon Barad
Alon Barad
7 views•5 min read