Security Digest · Oct 16, 2026 · Vulnerability · Library
Pillow 13.0.0: Critical Image-Parsing Memory Bugs Fixed
Pillow 13.0.0 fixes heap overflows in MPO/PSD, JPEG thumbnail and TIFF save paths plus an EPS Ghostscript flaw. No 12.x backport; needs Python 3.11+.
Our verdict
Patch this week
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.
Who must act: Any Python service that opens, thumbnails or re-saves untrusted images with Pillow, such as upload handlers, CMS and Django media pipelines, document converters and ML data loaders.
Who can relax: Code that only processes trusted, locally generated images, and Pillow builds older than 11.0.0 for the MPO/PSD bug (they still need 13.0.0 for the others).
- Affected
- Pillow 11.0.0 through 12.3.0 (CVE-2026-96639, multi-frame PSD/MPO/DCX/MIC)
Pillow 12.3.0 and earlier with libjpeg-turbo 3.x, including official wheels (CVE-2026-112403)
Pillow 2.0.0 through 12.3.0 (CVE-2026-112393, TIFF save to BytesIO)
Pillow 2.6.0 through 12.3.0 (CVE-2026-112900, EPS via Ghostscript)
Debian bookworm, trixie and forky pillow packages (vulnerable as of Oct 21, 2026) - Fixed in
- Pillow 13.0.0 (requires Python 3.11 or later)
Debian sid pillow 13.0.0-1 - CVSS
- 9.8 (v3.1, CNA)
- EPSS
- 0.5% (percentile 44)
- CISA KEV
- Not listed
- Exploitation
- Public proof-of-concept
- Severity
- Critical
What to do
- Find every Pillow install: pip show pillow, or pip list | grep -i pillow, in each image and virtualenv.
- Upgrade with pip install --upgrade 'pillow>=13.0.0', then rebuild and redeploy containers.
- Services still on Python 3.10 cannot install 13.0.0: plan the Python upgrade, and apply the workarounds meanwhile.
- Until upgraded, call img.load() before thumbnail() or pass reducing_gap=None, and restrict Image.open(formats=[...]) to the formats you need, excluding EPS, PSD, MPO, DCX and MIC.
- Never pass user-controlled filenames to Image.open(); open uploads as file objects or from server-generated paths.
- Check distro python3-pil packages separately; Debian stable releases were still unfixed as of Oct 21, 2026.
How to check if you are affected or compromised
- python3 -c "import PIL; print(PIL.__version__)" in each runtime; anything below 13.0.0 is affected.
- python3 -c "from PIL import features; print(features.version('libjpeg_turbo'))" shows whether the JPEG bug's libjpeg-turbo 3.x precondition applies.
- Watch image workers for segfaults, glibc heap errors such as 'malloc(): corrupted top size', and restarts tied to specific uploads.
- Hunt for unexpected child processes (gs, shells) spawned by Python image workers.
What happened#
On October 16, 2026, the Pillow project released Pillow 13.0.0. Its security section lists dozens of fixes, mostly in image decoders and encoders, with severities from critical to low. The repository advisories went public on October 17, and the CVE records followed on October 19 and 21. These four are the ones to read first:
- CVE-2026-96639 (GHSA-v9pv-5gc8-w2m6, CVSS 3.1 9.8). Multi-frame loaders can reuse native storage sized for a narrower frame after a later frame changes mode. Per the CVE record, crafted PSD, MPO, DCX or MIC files then write past the allocation. The record says the MPO path can also reach command execution "in demonstrated runtime-specific profiles". The reporter notes this is not universal RCE. It affects 11.0.0 through 12.3.0.
- CVE-2026-112403 (GHSA-8g5g-8vmr-9782).
thumbnail()callsdraft(), which asks libjpeg for downscaled output. Lossless (SOF3) JPEGs ignore that request under libjpeg-turbo 3.x, so full-width rows overflow a smaller heap buffer. The advisory says official Pillow wheels bundle libjpeg-turbo 3.x. Builds on libjpeg-turbo 2.x or IJG libjpeg reject the file. RestrictingImage.open(..., formats=["JPEG"])does not help, because the file is a valid JPEG. The report credits Anthropic's Claude for the find, validated by Ada Logics. - CVE-2026-112393 (GHSA-332p-7hrc-92wf). Re-saving a TIFF to an in-memory target such as
io.BytesIOcan write attacker-supplied tag bytes past a heap buffer and leak stale heap bytes. Saves to real file paths are unaffected. The bug dates back to Pillow 2.0.0 (2013). - CVE-2026-112900 (GHSA-w889-685w-c8fh). For EPS files, Pillow passes the filename to Ghostscript unsanitized. A name beginning with
-or@injects Ghostscript arguments even with-dSAFER. Command execution also requires an@argument file the attacker controls.
Severity labels disagree between sources. The CVE records score the last three 9.2 (CVSS 4.0). Pillow's own advisories label the JPEG bug High and the EPS bug Moderate, and the release notes rank the EPS bug Medium.
Who is affected#
Anyone running Pillow 12.3.0 or earlier on images they did not create. That includes upload handlers that generate thumbnails, CMS media libraries, PDF and document converters, and ML pipelines that read scraped datasets. Pillow 13.0.0 requires Python 3.11 or later, and PyPI has no 12.x security release, so Python 3.10 services have no upstream fix. As of October 21, the Debian tracker shows bookworm, trixie and forky still vulnerable, with only sid fixed (13.0.0-1).
Do you really need to act?#
Yes, if untrusted images reach Pillow. Each bug fires from file contents during routine calls such as open(), seek(), thumbnail() and save(), not exotic APIs. The JPEG bug needs no special format at all. Reproducers are attached to the public advisories, and CISA's enrichment of CVE-2026-112393 records a proof of concept. No in-the-wild exploitation was reported as of October 21, 2026, and none of these CVEs is in CISA KEV. The EPS bug is narrower: it needs an attacker-influenced filename, and Ghostscript must be installed.
What to do now#
- Inventory:
pip show pillowin every virtualenv and image, andpip-auditwhere you use it. - Upgrade:
pip install --upgrade 'pillow>=13.0.0', pin it in requirements or lock files, and rebuild containers. Review 13.0.0's breaking changes first, such as the dropped Python 3.10 support and the removedImage._show. - Until you can upgrade, per the JPEG advisory, call
img.load()beforethumbnail()or passreducing_gap=None. Open uploads with an explicitformats=list that leaves out EPS, PSD, MPO, DCX and MIC unless you need them. - Never pass user-supplied filenames to
Image.open(). Open a file object or a server-generated path instead. - Run image decoding in a separate, low-privilege worker without network egress, so a memory-corruption bug stays contained.
How to tell if you were hit#
Check versions with python3 -c "import PIL; print(PIL.__version__)". Check the bundled JPEG library with features.version('libjpeg_turbo') from the features module. In logs, look for image workers that segfault or abort with glibc heap errors such as malloc(): corrupted top size, especially if one upload triggers it repeatedly. Look for Ghostscript (gs) or shell processes spawned by Python workers that should not run them. Treat a worker that crashed on attacker-supplied files as possibly compromised, and rotate the secrets it could read.
Timeline#
- — Pillow 13.0.0 is released on PyPI.
- — Pillow publishes the repository security advisories.
- — CVE-2026-112393, CVE-2026-112403 and CVE-2026-112900 are published.
- — GitHub's advisory database lists the first critical advisory, with more following Oct 21.
- — CVE-2026-96639 is published.
Vulnerability records
- CVE-2026-96639 · Pillow is a Python imaging library. From 11.0.0 until 13.0.0, multi-frame loaders can retain an ImagingCore allocation created for a narrow frame mode while a…
- CVE-2026-112403 · Pillow is a Python imaging library. Prior to 13.0.0, Pillow's JPEG decoder can write a full-width scanline into a buffer sized for a requested draft scale.
- CVE-2026-112393 · 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…
- CVE-2026-112900 · Pillow is a Python imaging library. From 2.6.0 until 13.0.0, Pillow is vulnerable to argument injection when invoking Ghostscript for EPS input.
Sources
Original sources first: vendor and project advisories, CVE and government records, the discoverers’ write-ups. Every claim above links to one of these. See how the Security Desk works.
Original and primary sources
- Pillow — 13.0.0 release notes (Security) pillow.readthedocs.io
- Pillow / GitHub — GHSA-v9pv-5gc8-w2m6: multi-frame loaders reuse stale native image storage (CVE-2026-96639) github.com
- Pillow / GitHub — GHSA-8g5g-8vmr-9782: heap buffer overflow in ImagingJpegDecode (CVE-2026-112403) github.com
- Pillow / GitHub — GHSA-332p-7hrc-92wf: heap buffer overflow in _tiffWriteProc (CVE-2026-112393) github.com
- Pillow / GitHub — GHSA-w889-685w-c8fh: argument injection in Ghostscript call (CVE-2026-112900) github.com
- CVE record — CVE-2026-96639 cve.org
- CVE record — CVE-2026-112403 cve.org
- CVE record — CVE-2026-112393 cve.org
- CVE record — CVE-2026-112900 cve.org
- PyPI — Pillow 13.0.0 pypi.org
- Pillow docs — features module (libjpeg_turbo) pillow.readthedocs.io
- Debian security tracker — CVE-2026-112403 security-tracker.debian.org