Vulnerabilities

Pillow 13.0.0 fixes critical image flaws that can run code

Pillow 13.0.0 fixes critical EPS, FlashPix, TIFF and JPEG flaws in Python’s top image library. Why UK upload pipelines should patch now.

Illustration of a software bug over code representing critical flaws in the Pillow Python image library.

Pillow, the image library at the heart of most Python services that touch pictures, has shipped a heavyweight security release with several memory corruption and command injection fixes rated critical. Any UK organisation that accepts image uploads, generates thumbnails or runs Python data pipelines should treat version 13.0.0 as a priority upgrade.

What happened

The Pillow maintainers released version 13.0.0 on 16 October 2026 and published the accompanying GitHub security advisories the following day. It drew little attention until OX Security published an analysis on 22 October drawing out three CVEs, each scored 9.2 under CVSS v4.0, and The Hacker News followed on 23 October.

The scale of the release is unusual. The 13.0.0 release notes list dozens of security entries across critical, high, medium and low tiers, covering JPEG, TIFF, EPS, FlashPix, PDF, WMF, GIF and several older formats. OX Security puts Pillow at roughly 436 million downloads a month.

There are no reports of any of these bugs being exploited in the wild. However, The Hacker News reports that the CVE record flags a public proof of concept for the TIFF issue, and one of the critical advisories includes a working demonstration of code execution from a single crafted file.

The technical picture

CVE-2026-112900 (EPS and Ghostscript). When Pillow opens an EPS image it calls out to Ghostscript and hands over the file name without first making it an absolute path. A name beginning with a hyphen is read as a Ghostscript option, and Ghostscript’s argument-file syntax lets an attacker pull in further options from a second file they control. The advisory says the default -dSAFER mode does not stop this. Pillow’s own maintainers rate it moderate because the attacker must influence the file name, while the GitHub-assigned CVE record scores it 9.2. It affects versions 2.6.0 to 12.3.0, and only matters on hosts where the gs binary is installed.

FlashPix decoding (GHSA-5x8w-8jj5-q52h). This is the one I would lose sleep over. The maintainers rate it critical: a heap overflow in the FPX tile decoder that the reporter turned into command execution from one call to Image.open(). Pillow identifies FlashPix files by their OLE2 signature rather than their extension, so a file named avatar.png can still reach the vulnerable code. It is only reachable when the optional olefile package is installed, but it can easily arrive as a transitive dependency.

CVE-2026-112393 (TIFF write). A bug dating back to 2013 miscalculates buffer growth when a compressed TIFF is written to an in-memory object such as io.BytesIO. Output over 64 KiB can overflow the heap and leak stale memory into the resulting file. The advisory notes the reporters reached code execution only by pairing it with a separate address leak. Saving straight to disk avoids the problem.

CVE-2026-112403 (JPEG thumbnails). When thumbnail() asks the JPEG decoder for a scaled-down image, lossless JPEGs decoded by libjpeg-turbo 3.x ignore the scaling request and return full-width rows into a buffer sized for the smaller image. The official Pillow wheels are built against libjpeg-turbo 3.x, so most pip installs are in scope. The advisory reports a crash rather than proven code execution.

Alongside these, the release notes list a second critical item involving stale native image storage being reused after a mode change and a long tail of decompression bomb and resource exhaustion bugs useful for denial of service.

Key figures for the Pillow 13.0.0 security release: dates, CVSS scores, download volume, oldest bug, exploitation status and fix.

Why it matters for UK organisations

Pillow is rarely something a team chooses on purpose. It arrives underneath Django and Flask applications, document and PDF pipelines and almost every machine learning stack. UK public sector digital services, universities, retailers with product catalogues and fintechs running identity checks on photographed documents all process images supplied by members of the public, often in exactly the patterns these advisories describe: open an upload, resize it, re-encode it in memory and store the result.

The bigger issue is visibility. Many organisations cannot quickly answer the question “where do we run Pillow, and which version?” because it sits inside container base images, Lambda layers, vendored wheels in commercial products and data science notebooks that never went through change control. Pillow 13 also drops support for Python 3.10, so estates still on that interpreter face a runtime upgrade before they can take the fix. That friction is how vulnerable versions linger for months.

There is a governance angle too. Supply chain assurance, whether driven by customers, auditors or regulators, increasingly assumes organisations know which third-party components they ship. A widely reported library flaw like this is a good, low-drama test of whether your software bill of materials process actually works.

Expert view

When we test web applications, image upload handlers are among the first places we look, because they combine untrusted input with complex native parsing code that developers treat as a black box. Format sniffing makes this worse: an allow-list that checks file extensions gives little protection if the library decides what a file is by reading its first bytes. The FlashPix issue is a textbook example.

I would also urge caution with the scores. The CVSS figures of 9.2, and the critical FlashPix rating, do not capture the preconditions: Ghostscript must be present for the EPS bug, olefile for the FlashPix one, and specific code paths for TIFF and JPEG. That should shape the order you patch in, not whether you patch. In my experience, a condition that looks unusual on paper is usually the default somewhere in a large estate.

The JPEG thumbnail bug is credited in its advisory to Anthropic’s AI-assisted research, validated by Ada Logics. It fits a wider pattern this year: machine-assisted bug hunting is finding old memory safety flaws in mature, heavily used libraries faster than downstream consumers are updating. Patch cadence for open source dependencies needs to tighten accordingly.

What to do now

  1. Find every copy. Query your SBOMs, container registries and dependency scanners for Pillow below 13.0.0, including copies bundled inside third-party products and base images. This maps to the Cyber Essentials security update management control.
  2. Upgrade to Pillow 13.0.0 and rebuild affected images, wheels and layers rather than patching running containers. Plan the Python 3.11 move for anything still on 3.10.
  3. Prioritise internet-facing upload paths: avatar and profile images, document submission portals, thumbnail generators and anything that opens files from members of the public.
  4. Reduce attack surface while you patch. Remove Ghostscript from hosts that process untrusted images, never let user input shape file names passed to Pillow, and restrict the formats Pillow will open to those you genuinely need. This aligns with the secure configuration control.
  5. Apply interim workarounds where upgrades lag: call load() before thumbnail() on untrusted JPEGs, and treat in-memory TIFF re-encoding of user images as a sensitive path.
  6. Isolate image processing. Run it in low-privilege, sandboxed workers with no access to secrets, so a parser bug yields as little as possible.

Bottom line

There is no sign of active exploitation, but Pillow sits in an enormous number of UK systems, the advisories are public and at least one comes with a working demonstration. Use this release to prove you can find and update a deeply buried dependency within days, not quarters.

Sources