high · 7.5CVE-2026-55379Jul 20, 2026

CVE-2026-55379: Pillow BdfFontFile Decompression Bomb Protection Bypass

Shubham Kandhare
Security Engagement Manager, SecureLayer7

A crafted BDF font file can make Pillow silently allocate gigabytes of memory, completely bypassing the decompression bomb limits that protect Image.open().

Packagepillow
Ecosystempip
Affected< 12.3.0
Fixed in12.3.0

The problem

Pillow's `Image.open()` enforces a pixel-count ceiling via `_decompression_bomb_check()` and raises `DecompressionBombError` above ~178 million pixels. The BDF font loader in `PIL/BdfFontFile.py` never calls that check.

When `Image.frombytes()` fails on an empty `BITMAP` section, `bdf_char()` falls through to `Image.new("1", (width, height))` using the raw `BBX` dimensions from the file. A single glyph declared as `BBX 20000 20000` allocates ~47 MB of C-heap silently. A file with 256 glyphs at `BBX 8000 8000` reaches ~1.95 GB, all with no exception raised.

Proof of concept

A working proof-of-concept for CVE-2026-55379 in pillow, with the exact payload below.

text
STARTFONT 2.1
SIZE 16 75 75
FONTBOUNDINGBOX 16 16 0 -4
STARTPROPERTIES 1
COMMENT placeholder
ENDPROPERTIES
CHARS 1
STARTCHAR A
ENCODING 65
SWIDTH 500 0
DWIDTH 8 0
BBX 20000 20000 0 0
BITMAP
ENDCHAR
ENDFONT

The vulnerability is triggered by the empty `BITMAP` section. `Image.frombytes()` raises `ValueError` when there are zero hex rows to decode, and the except branch calls `Image.new("1", (width, height))` directly. `Image.new()` only calls `_check_size()`, which validates that dimensions are non-negative, but performs no pixel-count limit check.

The fix in commit `0a263e6264aa5399988d9acd3bbfbca2ca3ec77d` adds `Image._decompression_bomb_check((width, height))` before the `Image.new()` call, mirroring the guard already present in `Image.open()`. CWE-789: Memory Allocation with Excessive Size Value.

The fix

Upgrade Pillow to 12.3.0 or later. If you cannot upgrade immediately, avoid passing untrusted BDF files to `BdfFontFile()` or `ImageFont.load()`. There is no in-process workaround short of pre-validating `BBX` dimensions against `Image.MAX_IMAGE_PIXELS` before loading.

Reporter not attributed.

References: [1][2][3][4][5][6]

Related research