Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessSubmit image data re-encoded by app
-
DeliverySupply TIFF tag libtiff rejects (e.g. PREDICTOR=3)
-
ExploitTrigger error path freeing output buffer
-
ExecutionOpen TIFF handle flushes into freed memory
-
ImpactCrash 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. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – 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
Affected Packages
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
AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
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.
Primary rating from Vendor (GitHub_M).
CVSS VectorVendor: GitHub_M
Lifecycle Timeline
2DescriptionCVE.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.
Blast Radius
ecosystem impact- 2,395 pypi packages depend on pillow (1,190 direct, 1,242 indirect)
Ecosystem-wide dependent count for version 11.3.0.
Threat Intelligence Overview
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.
What every action level means
SSVC AssessmentENISA
Priority Score
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.
libImaging/TgaRleDecode.c in Pillow 9.1.0 has a heap buffer overflow in the processing of invalid TGA image files. Rated
Denial of service in Python Pillow (versions 8.2.0 through 12.2.0) allows remote attackers to exhaust memory during JPEG
Out-of-bounds memory disclosure in Python Pillow before 12.3.0 lets an attacker who supplies a crafted McIdas AREA image
Heap out-of-bounds write in Python Pillow prior to 12.3.0 lets an attacker who controls the rank-filter size parameter c
Uncontrolled memory consumption in Python Pillow (PIL) versions 5.1.0 through 12.2.x allows a remote attacker to cause d
The package pillow 5.2.0 and before 8.3.2 are vulnerable to Regular Expression Denial of Service (ReDoS) via the getrgb
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
Integer overflow in the ImagingResampleHorizontal function in libImaging/Resample.c in Pillow before 3.1.1 allows remote
Python Image Library (PIL) 1.1.7 and earlier and Pillow 2.3 might allow remote attackers to execute arbitrary commands v
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
Pillow through 8.2.0 and PIL (aka Python Imaging Library) through 1.1.7 allow an attacker to pass controlled parameters
An issue was discovered in Pillow before 8.1.1. Rated critical severity (CVSS 9.8), this vulnerability is remotely explo
EUVD-2026-104632
GHSA-4rr5-89j8-mwwm
NVD
CVE.org
EPSS
Vulnrichment
Exploit-DB