Security Digest · Vulnerability record
CVE-2026-112393: Pillow: Heap buffer overflow in _tiffWriteProc when saving TIFF to BytesIO
Pillow is a Python imaging library. From 2.0.0 until 13.0.0, Pillow has a heap buffer overflow and stale-heap disclosure in tiffWriteProc when saving compressed TIFF data through libtiff to a target without a usable fileno(), such as BytesIO.
CVSS 9.2 Critical EPSS 0.5% · p44 Patch this week
Should you act?
Critical and remotely reachable
No known exploitation yet, but it is network-reachable without credentials. This signal is computed from CISA KEV, EPSS and CVSS data; it is not an editorial verdict.
- Not in CISA KEV, but CISA’s SSVC assessment records a public proof-of-concept, so attack code exists.
- EPSS 0.5%, percentile 44: FIRST’s model estimates a 0.5% chance of exploitation activity in the next 30 days, higher than 44% of all scored CVEs (low). EPSS is a probability, not a verdict.
- Remotely reachable with no login and no user interaction. If the vulnerable service is exposed to the internet, prioritize it.
- Only applies if your dependency tree includes
Pillow(PyPI) >= 2.0.0, < 13.0.0, fixed in 13.0.0. Check your lockfile, including transitive dependencies. - Editorial verdict: Patch this week. Pillow 13.0.0: Critical Image-Parsing Memory Bugs Fixed — If your service opens images that users or the internet supply, move to Pillow 13.0.0 this week; the worst bugs are memory corruption reachable from a crafted file, and reproducers are in the published advisories.
What it is
Pillow is a Python imaging library. From 2.0.0 until 13.0.0, Pillow has a heap buffer overflow and stale-heap disclosure in tiffWriteProc when saving compressed TIFF data through libtiff to a target without a usable fileno(), such as BytesIO. The callback sizes its allocation from the prior buffer size instead of the current write position, allowing an attacker-controlled out-of-line TIFF tag or retained ICC profile to be copied beyond the allocation after libtiff seeks forward. This overflow can crash the process and may allow code execution. Independently, unwritten alignment gaps in compressed TIFF output larger than 64 KiB can disclose stale heap bytes without a crafted tag. File paths and targets with real file descriptors are unaffected. This issue is fixed in version 13.0.0.
From the GitHub advisory
Pillow can write attacker-chosen data past the end of a heap buffer when it saves a TIFF image to an in-memory destination such as io.BytesIO rather than to a file. The same code also copies leftover heap memory from the process into the saved file. Anyone who can supply an image to a service that opens it and re-saves it as TIFF this way can trigger this with default settings. The attached reproducer crashes the process, and the overflow could potentially be developed further, but code execution is not demonstrated here.
The bug is in tiffWriteProc in src/libImaging/TiffDecode.c. This is the write callback for the in-memory sink that Pillow gives libtiff whenever the save target has no fileno(). While writing the directory, libtiff seeks past the current end of data and writes tag values there. tiffWriteProc sizes its realloc() from state->size + size instead of from the write position state->loc. As a result, the first out-of-line tag value written after that seek can run past the allocation by up to the size of the directory: 12 bytes per entry, 126 bytes in the minimal case, and 2384 bytes observed with a 331-entry directory. The overflowing bytes are the tail of a tag value taken from the uploaded file.
No save options are needed, because compression and tags are inherited from the source image. The overflow does require an attacker-sized out-of-line tag to reach libtiff. That happens when the opened TIFF is saved directly (ImageDescription, DocumentName or XMP), or through an embedded ICC profile, which survives copy() in im.info. The bytes libtiff skips for alignment are never initialised, so any compressed TIFF over 64 KiB written this way also leaks one stale heap byte per padding hole. That leak needs no crafted tag.
The attached reproducer builds a 131 KB PackBits TIFF and runs Image.open(...).save(io.BytesIO(), "TIFF"). Saving the same image to a file path succeeds, but the BytesIO save aborts with glibc's malloc(): corrupted top size. A second part of the script shows uninitialised heap bytes at the padding offsets of a BytesIO save that are zero in the file save. Saves to real files are unaffected. The defect dates to e782fe721e01 (2013) and has been present since Pillow 2.0.0.
Details
Weakness type: CWE-122.
Product: Pillow (PyPI) · Assigned by: GitHub_M · Published: 2026-10-19
Affected and fixed versions
| Ecosystem | Package | Vulnerable | First fixed |
|---|---|---|---|
| PyPI | Pillow | >= 2.0.0, < 13.0.0 | 13.0.0 |
| Vendor | Product | Affected versions (per CVE record) |
|---|---|---|
| python-pillow | Pillow | >= 2.0.0, < 13.0.0 |
Severity scores
| Scored by | CVSS | Score | Vector |
|---|---|---|---|
| GitHub_M | 4.0 | 9.2 Critical | CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N |
| GitHub | 4.0 | 9.2 | CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N |
- Attack vector: network (remotely reachable)
- Attack complexity: high (needs special conditions)
- Attack requirements: present (depends on deployment conditions)
- Privileges required: none (no login)
- User interaction: none
CVSS measures how bad a flaw is if exploited, not how likely exploitation is. Read it next to the exploitation data below.
Exploitation and urgency
- CISA KEV: not listed (no confirmed in-the-wild exploitation known to CISA).
- CISA SSVC assessment: exploitation poc, automatable no, technical impact total.
- FIRST EPSS (model of 2026-10-21): 0.53% probability of exploitation activity in the next 30 days; percentile 44.
Timeline
- — erroneo.us brief: Pillow 13.0.0: Critical Image-Parsing Memory Bugs Fixed
- — CVE record last updated
- — CVE record published by GitHub_M
- — GitHub-reviewed advisory GHSA-332p-7hrc-92wf published (critical)
Sources and references
Original sources first. Version and fix details should always be confirmed against the vendor or project advisory.
Vulnerability records
- GitHub Advisory GHSA-332p-7hrc-92wf github.com
- CVE.org record CVE-2026-112393 cve.org
- NVD entry CVE-2026-112393 nvd.nist.gov
Other references from the CVE record and advisory
- github.com github.com
- github.com github.com
- github.com github.com