CVE-2026-96639
### Summary Pillow multi-frame image loaders can retain native `ImagingCore` storage allocated for one frame while changing the Python-side image `mode` and decoder tiles for a later frame. If frame 0 allocates storage for a narrow mode such as `L`, and a later frame of the same dimensions switches to a wider mode such as `RGB` or `CMYK`, Pillow may decode wider pixels into the stale narrow native buffer. This causes native out-of-bounds writes and process crashes. In the MPO/JPEG path, I also demonstrated command execution in matching Python/Pillow runtime profiles through Pillow's documented `ImageSequence.Iterator` + `frame.load()` path. ### Details The root cause appears to be that `ImageFile.load_prepare()` only reallocates native storage when `_im is None`. It does not verify that the retained native `ImagingCore` storage still matches `self.mode` and `self.size`. Several multi-frame `seek()` / `_open()` paths can update `self._mode` and decoder tiles for a later frame without invalidating `_im`. The decoder then writes or reads according to the new frame mode while the native storage still belongs to the old frame mode. Verified affected surfaces: 1. **PSD** `PsdImageFile.seek()` can switch from grayscale/native `L` storage to RGB layer decoding while retaining `_im`. This produces attacker-controlled native out-of-bounds writes and reliable crashes. 2. **MPO/JPEG** A crafted two-frame MPO can make frame 0 allocate `L` storage, then make frame 1 decode `CMYK` / `RGB` data into the retained `L` storage. The documented `ImageSequence.Iterator` path reaches this with `frame.load()`. Verified native memory corruption, crash, over-read behavior, and scoped harmless-marker command execution on Pillow 12.3.0. 3. **DCX** `DcxImageFile.seek()` calls `PcxImageFile._open()`, which changes mode/tile state without a native-storage mode guard. A crafted DCX with `L` then `RGB` PCX frames produces retained-storage mismatch and crash. 4. **MIC** M
Properties
- Severity
- critical
- Summary
- Pillow multi-frame loaders can reuse stale native image storage after mode transitions
- Nvd fetched at
- 2026-10-22T22:14:18.200859+00:00
- Epss score
- 0.00565
- Cvss severity
- CRITICAL
- Cvss score
- 9.8
- Retrieved at
- 2026-10-22T22:17:36+00:00
- Ghsa published
- 2026-10-22T16:00:15Z
- Source url
- https://github.com/advisories/GHSA-v9pv-5gc8-w2m6
- Ghsa updated
- 2026-10-22T16:00:15Z
- Ghsa id
- GHSA-v9pv-5gc8-w2m6
- Last source
- FIRST EPSS
- Score
- 9.8
- Cvss version
- 3.1
- Cve id
- CVE-2026-96639
- Cvss vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- First seen by Signal
- 2026-10-21T22:34:38+00:00
- Is ghsa only
- false
- Vector
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Published at
- 2026-10-21T21:20:32.217
Related Entities (4)
HAS_WEAKNESS (2)
AFFECTS (1)
VULNERABLE_TO (1)
Explore deeper with Ninja Signal's threat intelligence graph