---
id: "CVE-2026-112405"
kind: "vulnerability"
aliases: ["CVE-2026-112405", "GHSA-cp9v-662q-vvx9"]
title: "Pillow: NULL pointer dereference in Image.merge via an unvalidated band 0"
severity: "high"
cvss: 8.7
epss: 0.0029100000392645597
exploited: false
status: "open"
category: "package"
products: [{"name": "pillow", "fixed": ["13.0.0"], "affected": ">= 12.0.0, < 13.0.0", "ecosystem": "pypi"}]
ecosystems: ["pypi"]
tags: ["cwe-476", "image-processing", "package", "pillow", "python", "self-hosted"]
not_affected_if: ["no-untrusted-image-input", "pillow-13-or-later", "pillow-below-12.0.0"]
published_at: "2026-10-19T22:17:08+00:00"
first_seen_at: "2026-10-23T19:11:32+00:00"
updated_at: "2026-10-23T21:57:19+00:00"
sources: [{"source": "ghsa", "url": "https://github.com/advisories/GHSA-cp9v-662q-vvx9", "first_seen_at": "2026-10-23T19:11:32+00:00"}, {"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-112405", "first_seen_at": "2026-10-23T21:57:19+00:00"}]
---

# Pillow: NULL pointer dereference in Image.merge via an unvalidated band 0

Pillow's Image.merge() skips validating band 0, so a single-band I or F image as the first band makes the native code dereference a NULL pointer. A crafted file opened through Pillow's IPTC plugin can crash the worker process, a denial of service rather than code execution.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- pypi:pillow affected >= 12.0.0, < 13.0.0 fixed 13.0.0

## How to check

pip show pillow (affected if version >= 12.0.0 and < 13.0.0)
If you process untrusted images with Pillow, check whether the worker runs in a restartable process

## Fix

Upgrade pillow to 13.0.0 or later.
Until then, reject or avoid untrusted files that Pillow opens via the IPTC path.

## Timeline

- 2026-10-23T19:11:32+00:00 ghsa https://github.com/advisories/GHSA-cp9v-662q-vvx9
- 2026-10-23T21:57:19+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-112405

## From the sources

### 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 02_poc.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.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
