GHSA-cp9v-662q-vvx9: Null Pointer Dereference
Summary Image.merge() checks the mode of every input band except band 0. If band 0 is a single-band I or F image, the native merge routine reads a pixel pointer that is NULL for those modes and the process crashes. The IPTC plugin reaches this from a plain Image.open() followed by a load, and IPTC has no magic-byte prefilter, so a crafted file with no recognizable header can drive it.
Details The validation loop skips band 0:
- src/PIL/Image.py:3795 iterates for band in bands[1:] and checks mode and size only for those.
For an I or F image the 8-bit plane image8 is NULL (only image32 is set). ImagingMerge dereferences bands[0]->image8[y] for the multi-band output modes:
- src/libImaging/Bands.c:302, :311, :321
The IPTC loader builds the band list from an attacker-typed sub-image and passes it to merge with the sub-image at index 0:
- src/PIL/IptcImagePlugin.py:156-160 - src/PIL/IptcImagePlugin.py:169 registers the opener with no accept function.
PoC python from PIL import Image
Band 0 is a single-band "I" image: its image8 plane is NULL. merge() validates only bands[1:], so the native ImagingMerge dereferences the NULL plane for band 0. band0 = Image.new("I", (4, 4)) Image.merge("RGB", [band0, Image.new("L", (4, 4)), Image.new("L", (4, 4))])
Run it: $ python 02poc.py Segmentation fault (core dumped)
Observed on a source build of commit 3e2ab96.
Under AddressSanitizer: ==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 #0 ImagingMerge src/libImaging/Bands.c:311 #1 merge src/imaging.c:2492 SUMMARY: AddressSanitizer: SEGV src/libImaging/Bands.c:311 in ImagingMerge The null address confirms the dereference of the missing image8 plane for band 0.
Impact NULL pointer dereference in a C extension. A crafted file opened and loaded through the IPTC path crashes the worker process. This is a hard crash, not a Python exception an application can catch.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
pip/pillowto a version that resolves this vulnerability.Fixed in 13.0.0
Event History
Frequently Asked Questions
Which applications are exposed to this issue?
Applications that use Pillow to open and load attacker-controlled image files are exposed through the IPTC plugin. The plugin is registered without an accept function, so a crafted file without a recognizable header can reach it.
What does an attacker need to trigger the crash?
An attacker needs to supply a crafted file that causes the IPTC loader to construct a merge operation with a single-band I or F image as band 0. Processing the file through Image.open() followed by image loading can trigger the NULL-pointer dereference.
What is the practical impact of successful exploitation?
The native image merge routine dereferences a NULL pixel-plane pointer, causing the process to crash. The provided information describes a denial-of-service condition.