Pillow, the widely used Python imaging library, has a critical flaw in the code that decodes FlashPix (FPX) images. According to the GitHub advisory GHSA-5x8w-8jj5-q52h, a single crafted file opened with Image.open() can trigger a heap buffer overflow and lead to arbitrary code execution. The issue is tracked as CVE-2026-112398, affects Pillow up to and including 12.3.0, and is fixed in 13.0.0.
If your Python application, CMS backend, or hosting platform thumbnails, resizes, or validates images that users upload, this is worth checking today. The advisory says the vulnerable path is reachable with no user interaction on services that process untrusted uploads, provided an optional dependency is present.
What happened
The advisory was published on Oct 17, 2026 in the python-pillow/Pillow repository and updated on Oct 23, 2026. It is rated critical and credits researcher Alex Bouffard. It lists the pip package pillow as affected in versions <= 12.3.0, with 13.0.0 as the patched version.
The research available to us does not include a CVSS score or a CWE entry, so we do not quote one. It also contains no information about whether the flaw is being exploited in the wild and no CISA Known Exploited Vulnerabilities entry, so exploitation status is unknown. Treat it as unconfirmed rather than as ruled out.
The advisory itself includes a proof of concept that, per the advisory, executes a chosen command on stock Pillow 12.2.0 on x86_64 Ubuntu 24.04. Our own cautious reading is that, with a public proof of concept, patching sooner is the safer course.
How the vulnerability works
FlashPix files are OLE2 compound documents. Per the advisory, Pillow recognizes them by their content signature rather than by file extension, as long as the optional olefile package is installed (Pillow documents it as the dependency for FPX and MIC support). That means a file named photo.jpg or avatar.png can still be routed to the FPX decoder if its contents say it is an OLE2 file.
Inside that decoder, a JPEG-compressed subimage is handled by choosing a pair of color modes based on color identifiers stored in the file itself. The advisory explains that the output buffer is sized from one of those modes (for example, 2 bytes per pixel), while the underlying JPEG library, left without a recognized color conversion, writes as many bytes per pixel as the embedded JPEG declares (the advisory says an attacker can set this to 4). The result is a write past the end of a heap buffer, with the overflow length driven by the image width and the overflowing content driven by the decoded pixel data.
In plain terms, this is an out-of-bounds write caused by a mismatch between how much memory was reserved and how much data the decoder produces. Because both the size and the content of the overflow are influenced by the attacker's file, memory corruption of this kind can often be turned into code execution, and the advisory's proof of concept demonstrates that. The advisory states the command runs as the user that runs the image processing. We are deliberately not reproducing exploit details here.
Who is realistically exposed
Exposure depends on two conditions: a vulnerable Pillow version, and the optional olefile package installed in the same environment. The advisory describes automatic FPX detection as depending on olefile, so without it that described path does not apply.
- Web applications that accept image uploads and then call Pillow to thumbnail, resize, convert, or validate them (profile pictures, product photos, document previews).
- Background workers and queues that process files from users, email attachments, or third-party feeds.
- Image proxies, media libraries, and CMS or e-commerce backends written in Python.
- Machine learning and data pipelines that load images from untrusted or scraped sources.
- Shared hosting and container images that bundle Python packages, where
olefilemay be present as a dependency of some other tool.
The impact depends on the privileges of the process. The advisory's demo ran as root inside a container. A worker running under a locked-down service account is a smaller target than one running as root, but code execution in the app process can still expose application secrets, database credentials, and uploaded customer data.
How to check your exposure
Run these checks in every environment that deploys Python code: production servers, containers, CI images, and worker hosts. Check the exact virtual environment your application uses, not just the system Python.
- List the installed Pillow version with
pip show pilloworpip list. Anything at 12.3.0 or earlier is in the affected range listed in the advisory. - Check whether
olefileis installed withpip show olefile. If it is present, automatic FPX detection by content is possible. - Search lock files and manifests (
requirements.txt,poetry.lock,Pipfile.lock) and your container images for pinned Pillow versions, including transitive dependencies pulled in by other packages. - Identify which services pass user-controlled files to
Image.open()and whether they run as root or with broad filesystem and network access. - Review upload and processing logs for unexpected crashes or aborts in image workers. A crash alone is not proof of an attack, but it is worth a look.
What to do now
The primary fix is to upgrade Pillow to 13.0.0, the patched version named in the advisory. As with any dependency upgrade, test your image handling in staging before rolling it out to production.
- Upgrade with
pip install --upgrade pillowor update the pinned version in your requirements or lock file to 13.0.0, then rebuild and redeploy containers. - Confirm the running version after deployment, since long-lived workers keep the old library loaded until restarted.
- If you cannot upgrade immediately, consider removing
olefilefrom environments that do not need FPX or MIC support. This follows from the advisory's description of the optional dependency, but treat it as a stopgap, not a substitute for patching, and test that nothing else relies on it. - Restrict what reaches the decoder. If your app only expects JPEG, PNG, or WebP, you can pass the
formatsargument toImage.open()so other formats are rejected. This is a general hardening measure and is not described in the advisory as an official mitigation. - Run image processing with least privilege: a non-root user, a read-only filesystem where possible, no access to production secrets, and limited outbound network access. Sandboxing or a separate worker container limits the damage of any decoder bug.
- Set sensible limits on upload size and image dimensions, since the advisory ties the overflow length to image width.
Detection and monitoring afterwards
Memory corruption bugs do not always leave clean traces, so combine several signals. Watch for repeated crashes or restarts of image-processing workers, unusual child processes spawned by your Python app, and unexpected outbound connections from upload-handling hosts. Keep a software inventory so you can answer quickly which services use which Pillow version the next time an advisory lands.
For the public-facing side of your site, a website firewall can add a layer in front of upload endpoints, but it is not a replacement for patching the library. You can also run a free malware scan and follow the steps in our guide to checking whether a website is hacked if you suspect something is off. Outside-in tools cannot see inside your application's dependencies, so a dependency audit on your own servers remains essential.
Timeline
| Date | Event |
|---|---|
| Oct 17, 2026 | Advisory GHSA-5x8w-8jj5-q52h published in python-pillow/Pillow |
| Oct 23, 2026 | Advisory updated |
The research contains no statement about exploitation in the wild, so we treat that status as unknown. If a primary source reports otherwise, that changes the urgency, but the advisory's public proof of concept is reason enough to patch promptly.
Sources
This article is based on the public sources below. Details can change as vendors and researchers publish more; check the original advisories before acting on version numbers.
- CVE-2026-112398 - GitHub Advisory Database (github.com)
Tags: Pillow, Python, CVE-2026-112398, RCE, file uploads, image processing
