Описание
Pillow: Controlled heap out-of-bounds write in Pillow ImageCmsTransform.apply() via output mode mismatch
Summary
Pillow's public ImageCms.ImageCmsTransform.apply(im, imOut) API can trigger
controlled native heap corruption when the caller supplies an output image whose
mode does not match the transform's declared output mode.
For example, a transform built as RGBA -> RGBA can be applied to an L output
image. Pillow checks dimensions only, then calls LittleCMS with the output row
pointer. LittleCMS writes RGBA-sized rows into a 1-byte-per-pixel L image row.
Details
src/PIL/ImageCms.py:ImageCmsTransform.apply() accepts an optional caller
supplied imOut:
If imOut is provided, Pillow does not check:
The C wrapper in src/_imagingcms.c unwraps both image cores and only checks
that the output dimensions are at least as large as the input dimensions:
findLCMStype() maps RGB, RGBA, and RGBX transform modes to LittleCMS
TYPE_RGBA_8, which writes 4 bytes per pixel:
So with a transform declared as RGBA -> RGBA, LittleCMS writes 4 * width
bytes to each output row. If the supplied output image is mode L, Pillow only
allocated 1 * width bytes for that row.
For width 4096:
The bug does not require a large image. Width 8 was enough to corrupt heap
metadata. At width 8, apply() returned to Python and printed after; glibc
detected the corrupted heap later during cleanup.
PoC
Tiny heap corruption trigger:
Observed locally on Pillow 12.3.0.dev0:
Controlled overwrite evidence PoC:
Run under gdb:
Observed on Pillow 12.3.0.dev0:
0x4443424144434241 is the attacker-controlled source pixel pattern
b"ABCDABCD" interpreted as a little-endian pointer-sized value.
Using source pixels (1, 2, 3, 4) similarly produced a faulting pointer of
0x403020104030201, matching the repeated pixel bytes.
Impact
This is a heap out-of-bounds write in Pillow's native ImageCms extension, reachable through public API.
Applications are impacted if untrusted users can control ImageCms transform
parameters and/or provide the output image object passed to
ImageCmsTransform.apply(). The source image pixels influence the bytes written
out of bounds.
Suggested fix
Validate modes before calling into the native transform:
The C extension should also defensively reject mismatched image modes before
calling cmsDoTransform().
Ссылки
- https://github.com/python-pillow/Pillow/security/advisories/GHSA-9hw9-ch79-4vh6
- https://nvd.nist.gov/vuln/detail/CVE-2026-59205
- https://github.com/python-pillow/Pillow/pull/9715
- https://github.com/python-pillow/Pillow/commit/a9ffc42bedf4fc0a7ef8d6486e7f9e81e3397721
- https://github.com/pypa/advisory-database/tree/main/vulns/pillow/PYSEC-2026-3453.yaml
- https://github.com/python-pillow/Pillow/releases/tag/12.3.0
Пакеты
pillow
< 12.3.0
12.3.0
Связанные уязвимости
Pillow is a Python imaging library. Prior to 12.3.0, Pillow's ImageCms.ImageCmsTransform.apply(im, imOut) API can trigger controlled native heap corruption when the caller supplies an output image whose mode does not match the transform's declared output mode. This issue is fixed in version 12.3.0.
Pillow is a Python imaging library. Prior to 12.3.0, Pillow's ImageCms.ImageCmsTransform.apply(im, imOut) API can trigger controlled native heap corruption when the caller supplies an output image whose mode does not match the transform's declared output mode. This issue is fixed in version 12.3.0.
Pillow is a Python imaging library. Prior to 12.3.0, Pillow's ImageCms.ImageCmsTransform.apply(im, imOut) API can trigger controlled native heap corruption when the caller supplies an output image whose mode does not match the transform's declared output mode. This issue is fixed in version 12.3.0.
Pillow is a Python imaging library. Prior to 12.3.0, Pillow's ImageCms ...