Every CVESearch/Get API key

CVE-2026-28231

pillow_heif Has Integer Overflow in Encode Path Buffer Validation that Leads to Heap Out-of-Bounds Read

5.5 MediumFix available

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

0.70%Up 0.7 points since Feb 28, 2026
90%50%10%1%

What each source reports

CVE List Score used5.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 MediumCVSS: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-90615.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 MediumCVSS: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-ph3x5.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
  • int32 product: 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_LIMITS is irrelevant
  • The encode path is reachable whenever an application calls pillow_heif.encode() or saves an image via Pillow with format="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 MediumCVSS: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
NVD5.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 MediumCVSS: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 CriticalCVSS: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
OSV5.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 MediumCVSS: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-ph3x5.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
  • int32 product: 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_LIMITS is irrelevant
  • The encode path is reachable whenever an application calls pillow_heif.encode() or saves an image via Pillow with format="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 MediumCVSS: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-22489.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 CriticalCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H
Updated
2026-11-02
OSVPYSEC-2026-22589.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 CriticalCVSS: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

Affected packages
PackageAffectedFixed
pi-heif
PyPI
before 1.3.0
1.3.0
pillow-heif
PyPI
before 1.3.0
1.3.0
pi-heif
PyPI
before 1.3.0, plus listed versions
0.10.00.10.10.11.00.11.10.12.0
Show 23 moreShow less
0.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-heif
PyPI
before 1.3.0, plus listed versions
0.1.100.1.110.1.40.1.50.10.0
Show 38 moreShow less
0.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-heif
openSUSE:Tumbleweed
before 1.3.0-1.1
1.3.0-1.1

History

History
RecordedChangedSources
factsOSV
first indexedCVE 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

Show 4 moreShow less
This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open