CVE-2026-32740: Verified Repro With Script Download
CVE-2026-32740: libheif: heap-buffer-overflow write decoding 1x4 grid of odd-height tiles
CVE-2026-32740 is verified against libheif · c. Affected versions: <= 1.21.2. Fixed in 1.22.0. Vulnerability class: OOB Write. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00159.
What Is CVE-2026-32740?
CVE-2026-32740 (GHSA-frfr-f3vg-2g6j) is a high-severity heap-buffer-overflow write vulnerability in libheif's grid tile compositing code, triggered by a crafted HEIF/AVIF image. Pruva reproduced it (reproduction REPRO-2026-00159).
CVE-2026-32740 Severity & CVSS Score
CVE-2026-32740 is rated high severity, with a CVSS base score of 8.8 out of 10.
High — serious impact or readily exploitable. Prioritize remediation.
Affected libheif Versions
libheif · c versions <= 1.21.2 are affected.
How to Reproduce CVE-2026-32740
pruva-verify REPRO-2026-00159 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00159/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-32740
Reproduced by Pruva's autonomous agents — 386 tool calls over 42 min. Full root-cause analysis and the complete transcript are below.
How the agent worked
Root Cause and Exploit Chain for CVE-2026-32740
Summary
CVE-2026-32740 is a heap-buffer-overflow write vulnerability in libheif's grid tile compositing code. When decoding a HEIF/AVIF image containing a grid of YCbCr 4:2:0 tiles with odd heights (e.g., 1×4 grid of 64×65 tiles), the chroma-plane copy logic in HeifPixelImage::copy_image_to() miscalculates the copy bounds. Due to independent ceiling-divisions for the destination offset (ys) and copy height (copy_height), their sum can exceed the allocated chroma plane height by one row. This results in a 32-byte (or 64-byte across Cb+Cr) out-of-bounds heap write of attacker-controlled chroma data.
Impact
- Package:
libheif(C++ HEIF/AVIF decoder/encoder library) - Affected versions:
<= 1.21.2 - Fixed version:
1.22.0 - Risk level: High (CVSS 3.1 base 8.8)
- Consequences: Any application that decodes untrusted HEIF/AVIF grid images with default build options is exposed. An attacker can craft a malicious file to write 64 bytes of fully controlled chroma data past the end of a heap allocation, enabling heap corruption, potential code execution via heap grooming, or denial of service.
Root Cause
The vulnerable function is HeifPixelImage::copy_image_to() in libheif/pixelimage.cc (v1.21.2, around line 964). When compositing a decoded tile into the grid canvas, the code computes:
uint32_t copy_height = std::min(src_height, channel_height(h - y0, chroma, channel));
uint32_t ys = channel_height(y0, chroma, channel);
For YCbCr 4:2:0, channel_height(n) uses ceiling division (n+1)/2. When the tile origin y0 is odd and the tile height is odd, ys + copy_height can exceed channel_height(total_height) by 1 row:
- Example: total height = 260 (4 × 65), last tile
y0 = 195 ys = ceil(195/2) = 98copy_height = ceil(65/2) = 33ys + copy_height = 131channel_height(260) = ceil(260/2) = 130- Overflow: 1 row (32 bytes for a 64-pixel-wide chroma row)
The fix (in libheif v1.22.0) rewrites copy_image_to to compute the copy height from the remaining plane size instead of recomputing it from the tile height:
uint32_t copy_width = std::min(src_width, channel_width(w, chroma, channel) - xs);
uint32_t copy_height = std::min(src_height, channel_height(h, chroma, channel) - ys);
This ensures ys + copy_height <= channel_height(h, chroma, channel), eliminating the rounding mismatch.
Reproduction Steps
The reproduction is fully automated by repro/reproduction_steps.sh.
What the script does:
- Builds libheif
v1.21.2(vulnerable) with AddressSanitizer (-fsanitize=address) and JPEG encoder/decoder support. - Builds libheif
v1.22.0(fixed) with the same ASan flags. - Compiles
repro/poc.c— a small C harness that uses the libheif C API to:- Create four 64×65 YCbCr 4:2:0 images.
- Add them as JPEG-encoded tiles into a 1×4 grid (overall 64×260).
- Write the resulting HEIF to
repro/poc.heif. - Decode the grid back via
heif_decode_image().
- Runs the decode step against the vulnerable build and captures ASan stderr to
logs/vuln_stderr.txt. - Runs the decode step against the fixed build and captures output to
logs/fix_stderr.txt. - Compares the two: confirms ASan heap-buffer-overflow in v1.21.2 and a clean run in v1.22.0.
- Writes a JSON runtime manifest with SHA256 of the PoC file and verdict.
Expected evidence:
- Vulnerable:
ERROR: AddressSanitizer: heap-buffer-overflowwith aWRITE of size 32inmemcpy→HeifPixelImage::copy_image_to→ImageItem_Grid::decode_and_paste_tile_image. - Fixed: No ASan diagnostic; decode completes with
Decoded OK.
Evidence
- Vulnerable ASan log:
logs/vuln_stderr.txt- Excerpt:
==2297==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x52500001118f WRITE of size 32 at 0x52500001118f thread T4 #0 in memcpy #1 in HeifPixelImage::copy_image_to(...) pixelimage.cc:964 #2 in ImageItem_Grid::decode_and_paste_tile_image(...) grid.cc:564
- Excerpt:
- Fixed run log:
logs/fix_stderr.txt- Contains only
Decoded OKwith no ASan error.
- Contains only
- PoC file:
repro/poc.heif(SHA256 recorded inrepro/runtime_manifest.json). - Build environments:
- Vulnerable:
external/libheif/build_vuln/libheif/libheif.so(v1.21.2 + ASan) - Fixed:
external/libheif/build_fix/libheif/libheif.so(v1.22.0 + ASan)
- Vulnerable:
Recommendations / Next Steps
- Upgrade to libheif
>= 1.22.0to obtain the correctedcopy_image_tologic. - Validate that any downstream packages (e.g.,
heif-convert, image viewers, thumbnailers) are rebuilt against the patched library. - Regression testing: Add a unit test that creates a 1×4 grid of odd-height 4:2:0 tiles and decodes it under ASan, asserting no heap-buffer-overflow.
- Fuzzing: The grid tile compositing path is a good target for guided fuzzing with odd-dimension chroma-subsampled tiles.
Additional Notes
- Idempotency:
repro/reproduction_steps.shhas been executed twice consecutively with identical results (ASan overflow on v1.21.2, clean on v1.22.0). - Edge cases: The overflow magnitude depends on the chroma row size. For a 64-pixel-wide image, one chroma row is 32 bytes (Cb or Cr), so the total overflow is 64 bytes across both chroma planes. The advisory notes that different tile heights (e.g., 33 or 65) and different canvas sizes can be used to target different heap bucket sizes.
- Limitations: The PoC requires a codec that preserves odd-height chroma planes correctly (JPEG in this reproduction). The built-in uncompressed codec truncates chroma height for odd dimensions, which would mask the overflow; therefore JPEG tiles are used.
CVE-2026-32740 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
Artifacts and Evidence for CVE-2026-32740
Scripts, logs, diffs, and output captured during the reproduction.
No artifacts available
How to Fix CVE-2026-32740
Upgrade libheif · c to 1.22.0 or later.
FAQ: CVE-2026-32740
How does the CVE-2026-32740 heap-overflow attack work?
Which libheif versions are affected by CVE-2026-32740, and where is it fixed?
How severe is CVE-2026-32740?
How can I reproduce CVE-2026-32740?
References for CVE-2026-32740
Authoritative sources for CVE-2026-32740 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.