Pillow: BMP RLE decoder memory-amplification DoS via unbounded delta escape / absolute mode
Summary
BmpRleDecoder can be forced to allocate gigabytes of memory from a kilobyte-sized crafted BMP file via unbounded growth in the delta escape and absolute mode branches.
Affected versions
All versions up to and including current HEAD (v13.0.0.dev0, commit e7a7ea84)
Root cause
BmpRleDecoder.decode() (BmpImagePlugin.py:327-395) builds a Python bytearray data with dest_length = xsize*ysize, looping while len(data) < dest_length. The loop condition is only checked at the TOP; individual branches append attacker-controlled amounts UNBOUNDED by dest_length:
- delta escape (line 370): data += b"\x00" * (right + up * self.state.xsize) with right,up in 0..255 -> up to ~255*xsize bytes in ONE iteration.
- absolute mode (line 385): data += bytes_read (up to 255).
Because a single delta can push len(data) to ~256 * (row size), a tiny RLE stream combined with a large-but-legal xsize (xsize*ysize just under MAX_IMAGE_PIXELS, ~89M) yields a multi-GB data bytearray (then copied again by bytes(data) and set_as_raw). No heap OOB (bytearray/set_as_raw are bounds-safe), but a severe memory-amplification DoS: the attacker file stays tiny.
Reproduction
Python 3.13, Pillow HEAD e7a7ea84
Attached: pillow_poc_bmp_rle_dos.py
A 1084-byte BMP (BI_RLE8, width=3,000,000, height=1 -> 3M px, passes bomb check) with one delta escape (00 02 00 150) produces ~429 MB data; measured peak RSS 911 MB. Scaling width toward the bomb limit and up=255 produces tens of GB from a ~1 KB file.
Suggested fix
Cap growth at dest_length in the delta and absolute branches, e.g. clamp the delta fill to (dest_length - len(data)) and stop appending once len(data) >= dest_length; reject deltas that would move the cursor beyond the image, matching the existing per-row clamp at line 341-343.
Credit: Yazan Balawneh - CyStack Security Team (GitHub: sonicnew)
Software afectado
Haz clic en una tecnología para ver todas sus vulnerabilidades.
| Plataforma | Paquete | Versiones vulnerables | Corregida en |
|---|---|---|---|
| Python (PyPI) | pillow | >= 9.1.0, < 13.0.0 | 13.0.0 |
Referencias
- https://github.com/python-pillow/Pillow/security/advisories/GHSA-24rc-8hj2-v98c
- https://nvd.nist.gov/vuln/detail/CVE-2026-96638
- https://github.com/python-pillow/Pillow/pull/10015
- https://github.com/python-pillow/Pillow/commit/e7794835e323ff2691d9b3a974cade1a44301b9a
- https://github.com/python-pillow/Pillow
- https://github.com/python-pillow/Pillow/releases/tag/13.0.0
- Vector CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H- Debilidad (CWE)
CWE-400, CWE-770- Plataforma
- Python (PyPI)
- Paquete
pillow- Publicada
- 22.10.2026
- Actualizado
- 22.10.2026 19:17
Fuentes y licencias
OSV / GitHub Advisory Database - GHSA-24rc-8hj2-v98c - CC BY 4.0
Historial de vulnerabilidades: pillow
Todas las vulnerabilidades publicadas de este paquete (Python (PyPI)), de la más reciente a la más antigua. Muestra si es un fallo aislado o un paquete que hay que vigilar.
- Entradas en total
- 99
- Primera → última
- 04.2014 10.2026
- Sin corrección
- 0
- Explotada en ataques
- 1
Distribución por gravedad
- Crítica 13
- Alta 57
- Media 27
- Baja 1
- Sin evaluar 1
Divulgaciones por año
- 2017: 1
- 2018: 0
- 2019: 1
- 2020: 10
- 2021: 20
- 2022: 8
- 2023: 3
- 2024: 2
- 2025: 1
- 2026: 41
antes: 12
-
Pillow: BMP RLE decoder memory-amplification DoS via unbounded delta escape / absolute mode esta entrada
Identifica las vulnerabilidades de tu aplicación
Con la integración de DockRay y el inventario de software activado, DockRay compara las versiones notificadas de los componentes con las vulnerabilidades conocidas y avisa de las coincidencias confirmadas. La cobertura depende de la tecnología compatible y de los avisos disponibles.