---
schema_version: '1.0'
id: security-20260721-e02209
url: https://osv.dev/vulnerability/GHSA-vjc4-5qp5-m44j
url_hash: e02209a52f6c05ea6a4744ed002d4ac90bd74a6fee7373cc59ebd7f674711def
canonical_url: https://osv.dev/vulnerability/GHSA-vjc4-5qp5-m44j
source: osv:ghsa
category: security/library
category_raw: cve/library
region: null
tags:
- cve
- CVE-2026-59204
- GHSA-vjc4-5qp5-m44j
- severity:CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
- pillow
- PyPI
lang: en
published_at: '2026-07-20T23:18:32Z'
fetched_at: '2026-07-21T06:55:47.640383Z'
updated_at: '2026-07-21T06:56:19Z'
status: published
content_hash: 4c1b71d2adfb383c2fab4f6dabbec0e39615856efe06768f00ac22b2f1c6ab91
content_changed_at: null
license_note: full
summary: Pillow JPEG2000 tiled decode retains a growing scratch buffer and can be
  used for denial of service
summary_source: rss
summary_en: Pillow JPEG2000 tiled decode retains a growing scratch buffer and can
  be used for denial of service
entities: []
key_facts: []
related: []
related_auto: []
title: 'CVE-2026-59204: Pillow JPEG2000 tiled decode retains a growing scratch buffer
  and can be used for denial of service'
---

# CVE-2026-59204: Pillow JPEG2000 tiled decode retains a growing scratch buffer and can be used for denial of service

## TL;DR
Pillow JPEG2000 tiled decode retains a growing scratch buffer and can be used for denial of service

## Key Points
- cve / CVE-2026-59204 / GHSA-vjc4-5qp5-m44j / severity:CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N / pillow / PyPI

## Details
**Severity:** CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
**Advisory:** GHSA-vjc4-5qp5-m44j (CVE-2026-59204)

**Affected (your watchlist):**
- `PyPI:pillow` 12.1.1 → fixed in 12.3.0 [docker/docker-llmwiki]
- `PyPI:pillow` 12.2.0 → fixed in 12.3.0 [docker/local+docker/mac]

**Details:**
### Summary
`src/libImaging/Jpeg2KDecode.c:853` accumulates `total_component_width` across every tile in a JPEG2000 image instead of recomputing it per tile. That accumulated value is then used in the `tile_bytes` calculation at `src/libImaging/Jpeg2KDecode.c:868`, which can make the decoder grow `state->buffer` via `realloc` at `src/libImaging/Jpeg2KDecode.c:876` up to roughly one full image's decompressed size even when each tile is small. A crafted tiled JPEG2000 file can therefore force substantially higher transient memory usage and trigger out-of-memory failures during decoding. Based on current evidence, the supported impact is denial of service, not memory corruption.

### Details
- Location: `src/libImaging/Jpeg2KDecode.c:853`
- Root cause: `total_component_width` is initialized only once before the tile loop and keeps growing across tiles. It is then used to derive `tile_bytes`, so later tiles are treated as if they had the combined component width of all earlier tiles.
- Dangerous operation: `tile_bytes` is promoted into `tile_info.data_size`, then `state->buffer` is grown with `realloc` at `src/libImaging/Jpeg2KDecode.c:876`.
- Reachability: any attacker-controlled JPEG2000 image with many tiles reaches this path during normal `Image.open(...).load()` decoding.


### PoC
The attached helper script and testcase were used:
[exercise_j2k_tile_realloc.zip](https://github.com/user-attachments/files/28099912/exercise_j2k_tile_realloc.zip)


Generate the testcase:

```bash
pythonexercise_j2k_tile_realloc.py make poc_3664_rgba_tile1832.jp2 \
  --size 3664 --tile 1832
```

Expected geometry from the helper:

- image size: `3664 x 3664`
- mode: `RGBA`
- tile size: `1832 x 1832` (`2x2` tiles)
- `image_bytes=53699584`
- uncapped RSS observed:
  - vulnerable build: `maxrss_kb=180264`
  - fixed comparison build: `maxrss_kb=138404`

Load it with the current vulnerable build:

```bash
python exercise_j2k_tile_realloc.py load poc_3664_rgba_tile1832.jp2
```

Load it again under a 160 MB address-space cap:

```bash
python exercise_j2k_tile_realloc.py load poc_3664_rgba_tile1832.jp2 --limit-mb 160
```

### Impact
Conservative impact: denial of service through memory exhaustion during JPEG2000 decoding.

**References:**
- https://github.com/python-pillow/Pillow/security/advisories/GHSA-vjc4-5qp5-m44j
- https://nvd.nist.gov/vuln/detail/CVE-2026-59204
- https://github.com/python-pillow/Pillow/pull/9704
- https://github.com/python-pillow/Pillow/commit/13ada41172142f2fd9f0906f615a00ea623a11ca
- https://github.com/python-pillow/Pillow
- https://github.com/python-pillow/Pillow/releases/tag/12.3.0

_Data: OSV.dev (upstream: ghsa) — https://osv.dev/vulnerability/GHSA-vjc4-5qp5-m44j_

## Source
元記事: [CVE-2026-59204: Pillow JPEG2000 tiled decode retains a growing scratch buffer and can be used for denial of service](https://osv.dev/vulnerability/GHSA-vjc4-5qp5-m44j) — published 2026-07-20T23:18:32Z
