VAITP Dataset

← Back to the dataset

CVE-2026-59203

Pillow's EPS parser allows a Denial of Service via an infinite loop.

  • CVSS 7.5
  • CWE-835
  • Resource Management
  • Remote

Pillow is a Python imaging library. From 12.0.0 through 12.2.0, Pillow's EPS parser in PIL/EpsImagePlugin.py accepts a negative byte count in the %%BeginBinary directive, allowing a crafted EPS file to cause Image.open() to seek backwards to the same directive and parse it repeatedly in an infinite loop. This issue is fixed in version 12.3.0.

CVSS base score
7.5
Published
2026-07-14
OWASP
A08 Software and Data Integrity Failures
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Resource Management
Subcategory
Resource Exhaustion
Accessibility scope
Remote
Impact
Denial of Service (DoS)
Affected component
Pillow
Fixed by upgrading
Yes

Solution

Upgrade Pillow to version 12.3.0 or later.

Vulnerable code sample

import io

def vulnerable_eps_parser(line_bytes, file_pointer):
    """
    A simplified representation of the vulnerable logic in Pillow's
    EpsImagePlugin.py before the fix.
    """
    # This code is assumed to be inside a loop reading an EPS file.
    # The line is expected to look like: b"%%BeginBinary: raster -100"

    # In the vulnerable code, the parser finds the '%%BeginBinary' directive.
    if line_bytes.startswith(b"%%BeginBinary:"):
        # It splits the line to get the parameters.
        parts = line_bytes.split(b":", 1)[1].strip().split(b" ")

        # It checks for a specific binary format ("raster").
        if len(parts) == 2 and parts[0] == b"raster":
            # THE VULNERABILITY:
            # The byte count is converted to an integer directly from the
            # file's content without validating if it is negative.
            byte_count = int(parts[1])

            # A negative 'byte_count' causes the file pointer to seek
            # backwards from the current position. If this logic is in a
            # loop, the program will seek back and re-read the same
            # '%%BeginBinary' line, causing an infinite loop (Denial of Service).
            file_pointer.seek(byte_count, io.SEEK_CUR)

Patched code sample

import re

# This code is a representative snippet from the _open() method in
# Pillow's PIL/EpsImagePlugin.py, demonstrating the fix for CVE-2026-59203.

# Assume 'fp' is an open file pointer to an EPS file and 'line' is a
# bytes string read from it, for example: b"%%BeginBinary: -100 hex ..."
# We also assume 'self' is an instance of the EpsImageFile class.

def patched_binary_parser(line, fp, self):
    """
    A function representing the fixed logic.

    :param line: A bytes string from an EPS file.
    :param fp: A file-like object.
    :param self: An image plugin instance.
    """
    if line.startswith(b"%%BeginBinary:"):
        m = re.search(rb"(\d+)\s+(\w+)\s+([0-9a-fA-F]+)", line)
        if m:
            length = int(m.group(1))

            # --- START OF FIX ---
            # The vulnerability was caused by accepting a negative 'length'.
            # A negative value would cause `fp.seek(length, 1)` to move the
            # file pointer backwards, leading to an infinite processing loop.
            # The fix is to check if the length is negative and raise an error.
            if length < 0:
                msg = "invalid length in %%BeginBinary section"
                raise OSError(msg)
            # --- END OF FIX ---

            # If the check passes, the code proceeds safely.
            # In the actual Pillow code, the following lines would execute:
            # self.tile = [("eps", (0, 0) + self.size, fp.tell(), (length,))]
            # fp.seek(length, 1)
            # self.mode = "P"
            # self.palette = ImagePalette.raw("RGB", m.group(3))
            print(f"Processing binary section of valid length: {length}")

Payload

%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: 0 0 1 1
%%BeginBinary: -1

Cite this entry

@misc{vaitp:cve202659203,
  title        = {{Pillow's EPS parser allows a Denial of Service via an infinite loop.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-59203},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-59203/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::