Skip to main content

Pillow CVE-2026-112396

| EUVDEUVD-2026-104632 MEDIUM
Use After Free (CWE-416)
2026-10-19 GitHub_M GHSA-4rr5-89j8-mwwm
5.9
CVSS 3.1 · Vendor: GitHub_M
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Submit image data re-encoded by app
  2. Delivery
    Supply TIFF tag libtiff rejects (e.g. PREDICTOR=3)
  3. Exploit
    Trigger error path freeing output buffer
  4. Execution
    Open TIFF handle flushes into freed memory
  5. Impact
    Crash worker (potential code execution)

Vulnerability Assessment

Weakness
CWE
ASVS 5.0
V15 - Secure Coding and Architecture Memory lifecycle management
MITRE ATT&CK

2 techniques across 2 tactics: Execution, Privilege Escalation

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

The application must save TIFF data to an in-memory buffer (BytesIO / clientstate->data path, NOT a file descriptor - the code explicitly branches on clientstate->fp) AND must let an attacker influence the TIFF tags/tiffinfo passed to Image.save(). Exploitation specifically requires a tag that libtiff REJECTS during encoding, so that TIFFWriteScanline fails inside ImagingLibTiffEncode - the documented trigger is a floating-point predictor (PREDICTOR=3) applied to integer sample data. Limiting factors: affected only from 11.3.0 up to (not including) 13.0.0; requires encoding to a memory buffer rather than a real file; requires attacker control over tag values, not merely over pixel data; and the reliable outcome is a crash - code execution is unproven. High attack complexity (AC:H) reflects the narrow, configuration-and-input-dependent trigger.

Impact

This is a genuine but moderate-priority memory-safety flaw, not a top-tier emergency. The CVSS 3.1 vector (AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H, base 5.9) models a network-reachable, unauthenticated, high-complexity bug whose only scored impact is availability (process crash). The 'may enable code execution' language and the RCE/Memory-Corruption tags raise the theoretical ceiling, but the scored confidentiality and integrity impact are both None, so the practical, confirmed consequence is a denial-of-service crash. No EPSS score, no CISA KEV listing, and no public exploit were provided, so exploitation status is 'no public exploit identified at time of analysis' - the committed test case (test_save_bytesio_encoder_error) demonstrates the crash condition but is a regression test, not weaponized exploit code. The signals are internally consistent rather than conflicting: high attack complexity (AC:H) aligns with the narrow trigger (libtiff must reject a tag mid-encode to a memory buffer), and the availability-only impact aligns with a use-after-free that reliably crashes but whose code-execution path is unproven. Net: patch in normal cycle; this is a high-CVSS-ceiling-but-low-demonstrated-risk issue absent evidence of reliable RCE.

Exploit ScenarioDerived

An application uses Pillow (11.3.0-12.x) to save user-supplied or user-influenced TIFF tags into an in-memory BytesIO buffer (e.g., a web service that re-encodes uploaded images). The attacker supplies tag values that libtiff rejects during encoding - such as a floating-point predictor (PREDICTOR=3) on integer sample data - which triggers the error path in ImagingLibTiffEncode, frees the output buffer without clearing the still-open TIFF handle, and causes later cleanup to write through the freed pointer, crashing the worker. No public weaponized exploit is known, though a proof-of-concept trigger exists as a regression test in the fix commit.

This Month Plan within 30 days. Why: MEDIUM severity (CVSS 4.0-6.9).
Patch available 0.5% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Oct 19, 2026

Heap use-after-free in Pillow 11.3.0 through 12.x can crash any Python process that encodes TIFF data into an in-memory buffer while an attacker influences the TIFF tags being written. When an application saves to BytesIO with a tiffinfo dictionary containing a tag libtiff rejects during encoding - the documented trigger is a floating-point predictor (PREDICTOR=3) applied to integer sample data - TIFFWriteScanline fails inside ImagingLibTiffEncode, the error path frees the output buffer without closing the TIFF handle, and a later cleanup flushes buffered bytes through the write callback into freed memory. The vector (CVSS 5.9, AV:N/AC:H/PR:N/UI:N, C:N/I:N/A:H) reflects unauthenticated but configuration-dependent reachability: exploitation needs the memory-buffer code path plus attacker-controlled tag values, and the reliable outcome is process termination, with code execution unproven; no public exploit identified at time of analysis, and the upstream fix commit ships a regression test rather than weaponized tooling.

RemediationAI

Upgrade to Pillow 13.0.0 or later (pip install --upgrade "Pillow>=13.0.0"), which applies commit dc95da20207827a062cfbf551ee9f6031465a8bb and moves buffer deallocation behind TIFFClose/TIFFCleanup while NULLing the handle and data pointers; details are in advisory GHSA-4rr5-89j8-mwwm. If upgrading cannot happen immediately, the most effective control is to stop passing attacker-influenced data as tiffinfo: build the tag dictionary server-side from a fixed allowlist (for example compression and dpi only) and drop or reject keys such as PREDICTOR, since the exploit primitive is a rejected tag rather than pixel content - the trade-off is that legitimate callers lose the ability to specify arbitrary TIFF metadata. A second option is to encode to a real file object rather than BytesIO where the workflow permits it, exercising the clientstate->fp branch instead of the freed in-memory buffer; this reduces exposure but is not a proven hard guarantee, so pair it with the allowlist. Additionally, run TIFF encoding in an isolated worker or subprocess with a memory cap and automatic restart so a triggered abort does not take down the parent service, accepting the cost of process supervision overhead, and note that Python-level exception handling cannot contain the fault because the invalid write happens during libtiff handle teardown in C.

Affected VersionsENISA

Pillow 11.3.0, < 13.0.0

Affected Packages

pypi pillow fix: 13.0.0

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in pypi

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

Pillow's TIFF encoder wraps libtiff in src/libImaging/TiffDecode.c, where ImagingLibTiffEncode writes scanlines through libtiff and ImagingLibTiffEncodeCleanup tears down the TIFF handle. The encoder has two output modes, distinguished by clientstate: when the destination is a real file descriptor libtiff owns the handle (clientstate->fp is NULL and a TIFFClose ultimately invokes the custom _tiffCloseProc), but when the destination is a Python-managed in-memory object such as io.BytesIO, clientstate->data points to a heap buffer and TIFFCleanup is used so that libtiff does not close the caller's file. The pre-fix error handling inside ImagingLibTiffEncode freed clientstate->data (and, in the fd case, called TIFFCleanup) at the moment a TIFFWriteScanline failure occurred, yet in the in-memory case the TIFF handle stayed open. That is the CWE-416 root cause: a use-after-free created by ordering, because closing or flushing the still-live handle later pushes buffered bytes back through the write callback into a buffer that has already been released. The fix (commit dc95da20, released in 13.0.0) removes the inline frees from the failure paths and consolidates teardown into ImagingLibTiffEncodeCleanup, which now closes or cleans up the TIFF handle first and only then frees clientstate->data, additionally zeroing both clientstate->tiff and clientstate->data to prevent double-free. Because the corruption happens inside CPython extension C code, a surrounding Python try/except around Image.save() will catch the raised OSError but cannot prevent the memory error that occurs during handle teardown.

Know when Pillow gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (GitHub_M) PRIMARY 5.9 MEDIUM
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
vuln.today AI 5.9 MEDIUM

AV:N since malicious tags arrive via processed image data; AC:H because the bug needs a specific libtiff-rejected tag on a memory buffer; PR:N/UI:N as the library performs the save; impact is crash-only, so A:H with C:N/I:N.

3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
4.0 AV:N/AC:H/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

Primary rating from Vendor (GitHub_M).

CVSS VectorVendor: GitHub_M

Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Lifecycle Timeline

2
Patch available
Oct 19, 2026 - 23:18 EUVD
CVE Published
Oct 19, 2026 - 21:02 cve.org
MEDIUM 5.9

DescriptionCVE.org

Pillow is a Python imaging library. From 11.3.0 until 13.0.0, Pillow has a heap use-after-free when libtiff rejects a tag while encoding TIFF data to an in-memory buffer. When an application saves attacker-influenced TIFF tags to BytesIO, libtiff can reject a tag during encoding in ImagingLibTiffEncode; the error path then frees the output buffer without closing or clearing the TIFF handle, and later cleanup flushes through the write callback into freed memory, which can crash the process and may enable code execution. This issue is fixed in version 13.0.0.

Threat Intelligence Overview

EPSS Score
0.5%
Top 61% exploitable
Prevalence
High
Pillow is among the most widely deployed Python imaging libraries in web apps
Threat Intel
1
1 source
Data Quality
6 sources
Confidence: High
EUVD NVD CVE.org EPSS Vulnrichment GHSA GitHub

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity MEDIUM
CISA KEV No
Public POC No
EPSS 0.5%
Patch available Yes
Active threat No
Deciding rule
MEDIUM severity (CVSS 4.0-6.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation
None
System Exposure· derived
Open
Automatable
No
Human Impact· derived
High
Technical Impact
Partial

Priority Score

30
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +30
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Use-after-free vulnerabilities occur when a program continues to access memory through a pointer after that memory has been deallocated.

Memory corruption occurs when a program writes data beyond the boundaries of allocated memory regions or accesses memory in unintended ways, violating the integrity of the process's address space.

Remote Code Execution represents the critical moment when an attacker successfully runs arbitrary code on a target system without physical access.

More in Pillow

View all
CVE-2022-30595 CRITICAL POC
9.8 May 25

libImaging/TgaRleDecode.c in Pillow 9.1.0 has a heap buffer overflow in the processing of invalid TGA image files. Rated

CVE-2026-59204 HIGH POC
8.7 Jul 14

Denial of service in Python Pillow (versions 8.2.0 through 12.2.0) allows remote attackers to exhaust memory during JPEG

CVE-2026-54058 HIGH POC
8.3 Jul 14

Out-of-bounds memory disclosure in Python Pillow before 12.3.0 lets an attacker who supplies a crafted McIdas AREA image

CVE-2026-59197 HIGH POC
8.2 Jul 14

Heap out-of-bounds write in Python Pillow prior to 12.3.0 lets an attacker who controls the rank-filter size parameter c

CVE-2026-59200 HIGH POC
7.5 Jul 14

Uncontrolled memory consumption in Python Pillow (PIL) versions 5.1.0 through 12.2.x allows a remote attacker to cause d

CVE-2021-23437 HIGH POC
7.5 Sep 03

The package pillow 5.2.0 and before 8.3.2 are vulnerable to Regular Expression Denial of Service (ReDoS) via the getrgb

CVE-2025-48379 HIGH POC
7.1 Jul 01

Pillow is a Python imaging library. In versions 11.2.0 to before 11.3.0, there is a heap buffer overflow when writing a

CVE-2016-4009 CRITICAL
9.8 Apr 13

Integer overflow in the ImagingResampleHorizontal function in libImaging/Resample.c in Pillow before 3.1.1 allows remote

CVE-2014-3007 CRITICAL
10.0 Apr 27

Python Image Library (PIL) 1.1.7 and earlier and Pillow 2.3 might allow remote attackers to execute arbitrary commands v

CVE-2026-96639 CRITICAL
9.8 Oct 21

Pillow versions 11.0.0 through 12.x (fixed in 13.0.0) can reuse a stale native ImagingCore buffer when a multi-frame ima

CVE-2021-34552 CRITICAL
9.8 Jul 13

Pillow through 8.2.0 and PIL (aka Python Imaging Library) through 1.1.7 allow an attacker to pass controlled parameters

CVE-2021-25289 CRITICAL
9.8 Mar 19

An issue was discovered in Pillow before 8.1.1. Rated critical severity (CVSS 9.8), this vulnerability is remotely explo

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy