Описание
Pillow GdImageFile._open(): image dimensions accepted without _decompression_bomb_check()
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):
When load() is subsequently called on the returned image object:
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:
GdImageFile was never updated to match, leaving a gap in protection.
Steps to reproduce
Proof of Concept script:
Expected output:
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:
Impact
- Availability: HIGH — a single 1,037-byte malicious
.gdfile 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.
Ссылки
- https://github.com/python-pillow/Pillow/security/advisories/GHSA-phj9-mv4w-65pm
- https://nvd.nist.gov/vuln/detail/CVE-2026-55380
- https://github.com/python-pillow/Pillow/commit/f39b0ae6624eb2d7c5c5d651d9bb5fdbd96a8675
- https://github.com/pypa/advisory-database/tree/main/vulns/pillow/PYSEC-2026-2256.yaml
- https://github.com/python-pillow/Pillow/blob/main/docs/releasenotes/12.3.0.rst
Пакеты
pillow
< 12.3.0
12.3.0
Связанные уязвимости
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.
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.
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.
Pillow is a Python imaging library. Prior to 12.3.0, PIL/GdImageFile.p ...