CVE-2026-96638

mediumpriority · track · 0EPSS 0.004 · 28 %ileUS
grimoire priorityP3 · Track
Exploitable?
—
no known exploitation
Likely / severe?
0.35% (28th) EPSS
CVSS 6.5 · medium
Is it mine?
2 products
Check your exposure
Who says so?
2 sources
nvd · osv

EPSS · scored 2026-10-27

Pillow is a Python imaging library. From 9.1.0 until 13.0.0, BmpRleDecoder.decode() in src/PIL/BmpImagePlugin.py permits crafted RLE BMP delta escapes and absolute-mode runs to append beyond the remaining dest_length without a per-branch cap. A delta can add roughly 255 image rows in one iteration, so a kilobyte-sized file with a large but permitted width can expand the data bytearray to hundreds of megabytes or more, causing memory-exhaustion denial of service. This issue is fixed in version 13.0.0.

01

cvss

Technical severity, 0–10. One row per scoring source.

6.5
010

base score 0–10 · higher = more severe · hover a vector to decode

v3.16.5mediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:Hsecondary · security-advisories@github.comexploitability 2.8 · impact 3.6
v3.16.5mediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:Hsecondary · OSV
v3.16mediumCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H/E:Usecondary · CVSS-BT (t0sche)
02

weaknesses

The CWE weakness classes this flaw belongs to.

03

affected products (2)

Products and version ranges known to be affected.

04

advisories (1)

Vendor and ecosystem advisories describing this.

  • GHSA-24rc-8hj2-v98cPillow: BMP RLE decoder memory-amplification DoS via unbounded delta escape / absolute mode2026-10-22ghsa · osvUS

    ## 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) [pillow_poc_bmp_rle_dos.py](https://github.com/user-attachments/files/30244974/pillow_poc_bmp_rle_dos.py)

05

sources

Which sources assert this record, and when.

published 2026-10-21modified 2026-10-27
07

references (4) nvd

External citations — patches, advisories, analysis.

scry

Attackers weaponise vulnerabilities like this against internet-exposed services. See what is exposed on your perimeter with a free passive scan.

Free scan