PHP2Shell: Read our blog on the critical RCE vulnerabilities affecting 70% of the Internet
Vulnerability DatabaseCVE-2026-112390

CVE-2026-112390: 
Python vulnerability analysis and mitigation

Overview

CVE-2026-112390 is an infinite loop vulnerability in Pillow, the Python imaging library, affecting versions 7.2.0 through 12.x (up to but not including 13.0.0). When processing a crafted Microsoft Image Composer (MIC) file containing an embedded TIFF stream with three or more Image File Directories (IFDs), Pillow's MicImageFile class enters a non-terminating loop while computing n_frames, consuming 100% CPU indefinitely. The vulnerability was published on October 19, 2026, and is fixed in Pillow 13.0.0. It carries a CVSS v3.1 base score of 7.5 (High) and a CVSS v4.0 base score of 8.2 (High) (GitHub Advisory, Red Hat).

Technical details

The root cause is classified as CWE-835 (Loop with Unreachable Exit Condition). The regression was introduced in commit 0b33a87 (April 2020, first released in 7.2.0), which removed MicImageFile's own n_frames property, causing it to inherit TiffImageFile.n_frames. The inherited implementation walks the embedded TIFF's IFD chain using self._seek(self.tell() + 1), relying on tell() to advance; however, MicImageFile.tell() returns the constant OLE stream index rather than the TIFF frame position, and MicImageFile.seek() calls TiffImageFile._open(), which resets _n_frames to None on every iteration. As a result, with three or more chained IFDs, the loop perpetually re-parses IFD 1 and never reaches IFD 2, making the exit condition unreachable. Exploitation requires only a 5.6 KB crafted OLE2 compound file and is triggered when an application reads im.n_frames, checks is_animated, or saves with save_all=True to TIFF, PDF, or WebP — but only if the optional olefile package is installed (GitHub Advisory, Fix Commit).

Impact

Successful exploitation causes a denial of service by holding a worker thread at 100% CPU indefinitely, with no exception raised, no memory growth, and no self-termination — only an external watchdog can stop it. Any unauthenticated attacker who can supply a crafted MIC file to an application that subsequently reads n_frames or uses save_all=True can render that worker permanently unresponsive. There is no confidentiality or integrity impact; the vulnerability is purely an availability issue affecting applications with olefile installed (GitHub Advisory).

Exploitability

No public proof-of-concept exploit code has been published, and there is no evidence of in-the-wild exploitation as of the disclosure date. The EPSS score is 0.0, and the vulnerability is not listed in the CISA Known Exploited Vulnerabilities catalog. The attack requires no authentication, no user interaction, and low complexity — an attacker simply needs to upload a crafted 5.6 KB MIC file to a vulnerable application — but exploitation is conditional on the olefile package being installed and the application touching n_frames or a save_all code path (GitHub Advisory, Red Hat).

Exploitation steps

  1. Craft the malicious file: Construct a minimal OLE2 compound file (≈5.6 KB) containing a storage named img0.ACI with a stream named Image that holds a TIFF with three or more chained IFDs (each with a non-zero next-IFD pointer except the last). The file requires no specific extension — Pillow identifies it by OLE magic bytes.
  2. Identify a vulnerable target: Find a web application or service that accepts image uploads and uses Pillow (versions 7.2.0–12.x) with olefile installed, and subsequently reads im.n_frames, checks is_animated, or re-saves with save_all=True to TIFF, PDF, or WebP.
  3. Upload the crafted MIC file: Submit the malicious file via the application's file upload endpoint. No authentication is required if the upload feature is public-facing.
  4. Trigger the infinite loop: The application calls Image.open() (which succeeds normally), then accesses im.n_frames or a save_all path. MicImageFile.n_frames enters the non-terminating IFD traversal loop, pinning the worker process at 100% CPU indefinitely.
  5. Sustain the denial of service: Repeat uploads with additional crafted files to exhaust all available worker threads, rendering the service fully unresponsive until an external watchdog or operator intervention restarts the workers (GitHub Advisory).

Indicators of compromise

  • Network: Repeated HTTP POST requests uploading small files (≈5–6 KB) with OLE2 magic bytes (D0 CF 11 E0 A1 B1 1A E1) to image upload endpoints; no file extension required.
  • Process: Worker processes (e.g., Python/Gunicorn/uWSGI workers) sustaining 100% CPU utilization for extended periods without completing; stack traces showing repeated calls to TiffImagePlugin.py:_setup, TiffImagePlugin.py:_seek, and TiffImagePlugin.py:n_frames (line ~1219).
  • Logs: Application logs showing image processing requests that never return a response or time out only via an external watchdog; absence of exceptions or error messages from the hung worker.
  • File System: Temporary files with no extension or .mic extension containing OLE2 magic bytes in upload/temp directories, with embedded TIFF data having three or more IFD entries (GitHub Advisory).

Mitigation and workarounds

Upgrade Pillow to version 13.0.0 or later, which resolves the issue by modifying TiffImagePlugin._open() and _seek() to not overwrite _n_frames or is_animated when already set by a subclass such as MicImageFile (Fix Commit, Pillow 13.0.0). If an immediate upgrade is not possible, consider the following interim mitigations:

  • Uninstall olefile: Without olefile, the MIC plugin is not registered and MIC files cannot be opened by Pillow, eliminating the attack surface.
  • Restrict file uploads: Block or reject files with OLE2 magic bytes (D0 CF 11 E0 A1 B1 1A E1) at the application or WAF layer.
  • Implement processing timeouts: Apply external timeouts (e.g., via process supervisors or async task timeouts) to image processing operations to prevent indefinite CPU consumption.
  • Avoid n_frames on untrusted input: Refactor code to avoid accessing n_frames or using save_all=True on user-supplied images without prior format validation.

Additional resources

Linux Distribution fix status

Fix availability across major Linux distributions and their releases.

Debian

Fixed

bookworm

pillow

Affected

sid

pillow: 13.0.0-1

Fixed

trixie

pillow

Affected

Ubuntu

Unknown

bionic (esm-infra)

pillow

Unknown

devel

pillow

Unknown

focal (esm-apps)

pillow-python2

Unknown

focal (esm-infra)

pillow

Unknown

jammy

pillow

Unknown

noble

pillow

Unknown

resolute

pillow

Unknown

trusty (esm-infra-legacy)

pillow

Unknown

RHEL / CentOS

Affected

RHEL 8

python-pillow.src

Affected

Source: This report was generated using AI

Related Python vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

GHSA-49wc-vv82-h8j7CRITICAL9.3
  • Python logoPython
  • harp-proxy
NoYesOct 24, 2026
GHSA-jpw8-42g9-g437HIGH7.4
  • Python logoPython
  • harp-proxy
NoNoOct 24, 2026
GHSA-vvjr-4qwm-6xjxMEDIUM4.8
  • Python logoPython
  • harp-proxy
NoNoOct 24, 2026
GHSA-rr87-p3f8-qhxjHIGHN/A
  • Python logoPython
  • memtomem
NoYesOct 24, 2026
GHSA-3v6c-9qpg-gf63HIGHN/A
  • Python logoPython
  • memtomem-stm
NoYesOct 24, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management