Media

Pillow: Decompression-bomb protection bypass via multi-frame seek() in MPO and DCX (MpoImageFile.seek / DcxImageFile.seek)

  • Publicada: 22.10.2026
  • Actualizado: 22.10.2026 19:17

Summary

Pillow's decompression-bomb protection (Image._decompression_bomb_check, gated by Image.MAX_IMAGE_PIXELS) is enforced only on the first frame, inside Image.open(). For multi-frame formats, seek() re-parses the target frame's header and resets self._size. GifImagePlugin and TiffImagePlugin re-run the bomb check on seek(), but MpoImageFile.seek() and DcxImageFile.seek() do not. A crafted MPO or DCX whose first frame is tiny (passing the check) but whose later frame declares enormous dimensions therefore bypasses the protection: loading that frame decodes an over-limit image and commits large amounts of memory — a denial of service (memory exhaustion / OOM).

Same class as the recently assigned CVE-2026-55379 (BdfFontFile), CVE-2026-55380 (GdImageFile) and CVE-2026-40192 (FITS GZIP).

Details

Image.open() → _open_core() runs _decompression_bomb_check(im.size) once, on the frame present at open time. Both vulnerable seek() methods re-parse a new frame and set a new self._size without re-checking:

  • PIL/MpoImagePlugin.py, MpoImageFile.seek(): calls JpegImagePlugin.JpegImageFile._open(self) (which sets self._size from the frame's JPEG SOF) and rebuilds self.tile, with no Image._decompression_bomb_check(self.size).
  • PIL/DcxImagePlugin.py, DcxImageFile.seek(): calls PcxImageFile._open(self) (which sets self._size from the page's PCX header), with no check.

Confirmed present in 12.3.0 (latest release) and on main (13.0.0.dev0). Compare GifImagePlugin._seek and TiffImagePlugin, which call _decompression_bomb_check correctly on seek.

PoC

Self-contained; the victim uses default MAX_IMAGE_PIXELS:

python
import io
from PIL import Image

# attacker builds the file (guard disabled only to CREATE the oversized frame)
Image.MAX_IMAGE_PIXELS = None
small = Image.new("RGB", (8, 8))
big   = Image.new("RGB", (14000, 14000), (120, 60, 30))   # 196,000,000 px > error threshold
buf = io.BytesIO()
small.save(buf, format="MPO", save_all=True, append_images=[big])
data = buf.getvalue()                                      # ~3 MB
Image.MAX_IMAGE_PIXELS = int(1024 * 1024 * 1024 // 4 // 3) # restore default

# victim (default limits)
im = Image.open(io.BytesIO(data))   # frame 0 (8x8) passes the bomb check
im.seek(1)                          # frame 1 (14000x14000) -> NOT re-checked  <-- bug
im.load()                           # decodes the over-limit image, commits memory
print("loaded over-limit frame:", im.size)

Measured on Pillow 12.3.0 (default limit 89,478,485 px; error threshold 178,956,970 px):

Vector File size Frame 1 Peak RSS
MPO (JPEG) ~3.0 MB 14000×14000 (196 Mpx) ~763 MB
DCX (PCX) ~6.2 MB 14000×14000 (196 Mpx) ~200 MB
Control: same image standalone — 196 Mpx DecompressionBombError (correctly blocked)

The DCX vector (0x3ADE68B1 magic + offset directory + two PCX pages) behaves identically via DcxImageFile.seek(). Scaling frame 1 toward JPEG's ~65500×65500 maximum drives multi-GB commitments from a small file, reliably OOM-killing the process.

Impact

Denial of service (memory exhaustion / OOM) — CWE-400 / CWE-1284, a bypass of Pillow's documented decompression-bomb mitigation. seek() + load() is the normal way to iterate frames (e.g. PIL.ImageSequence.Iterator, thumbnailers, converters, 3D-photo handlers). Because MPO is auto-detected from a JPEG carrying MPF metadata, a file served with a .jpg extension can be opened as MPO, so any application that iterates frames of untrusted images is exposed.

Suggested fix

Re-run the check after seek() re-parses a frame, mirroring GIF/TIFF:

python
# PIL/MpoImagePlugin.py — end of MpoImageFile.seek()
self.tile = [ImageFile._Tile("jpeg", (0, 0) + self.size, self.offset, self.tile[0][-1])]
Image._decompression_bomb_check(self.size)   # add
self.__frame = frame

# PIL/DcxImagePlugin.py — end of DcxImageFile.seek()
PcxImageFile._open(self)
Image._decompression_bomb_check(self.size)   # add

Software afectado

Haz clic en una tecnología para ver todas sus vulnerabilidades.

PlataformaPaqueteVersiones vulnerablesCorregida en
Python (PyPI) pillow < 13.0.0 13.0.0

Referencias

Puntuación CVSS 6.5/10
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-409
Plataforma
Python (PyPI)
Paquete
pillow
Publicada
22.10.2026
Actualizado
22.10.2026 19:17

Fuentes y licencias

OSV / GitHub Advisory Database - GHSA-p8hx-v2p6-rp84 - 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.

Todas (100) en el archivo
Entradas en total
100
Primera → última
04.2014 10.2026
Sin corrección
0
Explotada en ataques
1

Distribución por gravedad

  • Crítica 13
  • Alta 58
  • Media 27
  • Baja 1
  • Sin evaluar 1

Divulgaciones por año

  1. 2017: 1
  2. 2018: 0
  3. 2019: 1
  4. 2020: 10
  5. 2021: 20
  6. 2022: 8
  7. 2023: 3
  8. 2024: 2
  9. 2025: 1
  10. 2026: 42

antes: 12

Gravedad:
  1. Pillow: Decompression-bomb protection bypass via multi-frame seek() in MPO and DCX (MpoImageFile.seek / DcxImageFile.seek) esta entrada
    Media · 6.5 CVE-2026-96636 < 13.0.0 13.0.0
  2. Alta CVE-2026-112390 >= 7.2.0, < 13.0.0 13.0.0
  3. Crítica CVE-2026-112900 >= 2.6.0, < 13.0.0 13.0.0
  4. Alta · 7.5 CVE-2026-59200 >= 5.1.0, < 12.3.0 12.3.0
Mostrar más (20) Mostrando 20 de 72

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.

Conectar tu aplicación
Newsletter DockRay

La seguridad de tus aplicaciones en tu correo

Vulnerabilidades importantes, recomendaciones concretas y consejos prácticos para tus aplicaciones. Elige tus tecnologías y sigue lo que importa para tu proyecto.

  • Un resumen diario de nuevas vulnerabilidades, también las críticas.
  • Avisos sobre actualizaciones importantes.
  • Consejos prácticos sobre seguridad y monitorización de aplicaciones.

Déjalo vacío para recibir avisos de todas las tecnologías.

Suscripción gratuita. Date de baja con un clic en cualquier correo.