CVE-2026-59189 Overview
CVE-2026-59189 is an out-of-bounds read vulnerability in OpenEXR, the reference implementation of the EXR image format used across the motion picture industry. The flaw affects OpenEXRUtil versions 3.3.0 through 3.3.12 and 3.4.0 through 3.4.12. It resides in the TypedDeepImageChannel<T>::row() API, which returns an out-of-bounds pointer when a deep image has a non-zero dataWindow origin. Exploitation triggers a heap out-of-bounds read [CWE-125], leading to process crash and potential information disclosure under a controlled heap layout. The issue is fixed in OpenEXR 3.3.13 and 3.4.13.
Critical Impact
A crafted EXR deep image with a non-zero dataWindow.min causes row(0) to point outside the _sampleListPointers allocation, resulting in heap out-of-bounds reads, application crash, and possible leakage of adjacent heap memory.
Affected Products
- OpenEXR OpenEXRUtil versions 3.3.0 through 3.3.12
- OpenEXR OpenEXRUtil versions 3.4.0 through 3.4.12
- Applications and pipelines linking the vulnerable OpenEXRUtil library
Discovery Timeline
- 2026-08-25 - CVE-2026-59189 published to NVD
- 2026-08-25 - Last updated in NVD database
Technical Details for CVE-2026-59189
Vulnerability Analysis
The vulnerability originates in ImfDeepImageChannel and ImfFlatImageChannel inside OpenEXRUtil. Two coordinate models coexist in these classes. The at(x, y) accessor uses absolute image coordinates, with _base pre-offset by dataWindow.min. The row(r) accessor is documented as 0-based logical access relative to the channel's own row storage.
Because row(r) was implemented as _base + r * pixelsPerRow(), the offset applied to _base for the data window origin propagated into logical row indexing. When dataWindow.min is non-zero, row(0) no longer points at the first row of _sampleListPointers. Instead, it points to memory before or outside the allocation. Any caller that then dereferences the returned pointer performs a heap out-of-bounds read.
Under a controlled heap layout, an attacker who supplies a malicious EXR file can align sensitive data adjacent to the affected buffer. The out-of-bounds read then discloses that data through subsequent processing paths or crashes the host application.
Root Cause
The root cause is inconsistent coordinate handling between _base (offset by dataWindow.min) and the row index API, which is specified to be 0-based. The fix replaces _base with the underlying storage pointers _sampleListPointers (deep channels) and _pixels (flat channels), aligning row(r) with its documented semantics.
Attack Vector
Exploitation requires an attacker-supplied EXR file processed by an application using OpenEXRUtil. The user must open or ingest the file, satisfying the User Interaction requirement. Common targets include compositing tools, render farms, media asset pipelines, and web services that thumbnail or transcode EXR uploads.
// Source: https://github.com/AcademySoftwareFoundation/openexr/commit/37f03b6ed90f3dd9910f31de3a40f25f2bc2aca1
// Patch: src/lib/OpenEXRUtil/ImfDeepImageChannel.h
inline T* const*
TypedDeepImageChannel<T>::row (int r)
{
- return _base + r * pixelsPerRow ();
+ return _sampleListPointers + r * pixelsPerRow ();
}
template <class T>
inline const T* const*
TypedDeepImageChannel<T>::row (int r) const
{
- return _base + r * pixelsPerRow ();
+ return _sampleListPointers + r * pixelsPerRow ();
}
// Patch: src/lib/OpenEXRUtil/ImfFlatImageChannel.h
inline T*
TypedFlatImageChannel<T>::row (int r)
{
- return _base + r * pixelsPerRow ();
+ return _pixels + r * pixelsPerRow ();
}
Detection Methods for CVE-2026-59189
Indicators of Compromise
- Crashes or abnormal terminations in processes linking libOpenEXRUtil when handling EXR inputs from untrusted sources.
- AddressSanitizer or heap-checker reports flagging out-of-bounds reads inside TypedDeepImageChannel::row or TypedFlatImageChannel::row.
- EXR files with a non-zero dataWindow.min origin arriving through upload, email, or asset-ingestion pipelines.
Detection Strategies
- Inventory build dependencies and container images for OpenEXR versions in the 3.3.0–3.3.12 and 3.4.0–3.4.12 ranges using software composition analysis.
- Run fuzzing or differential parsing against EXR ingest endpoints using inputs that vary the dataWindow origin field.
- Alert on repeated segmentation faults in media-processing workers or render nodes correlated with EXR file ingestion.
Monitoring Recommendations
- Log EXR file metadata, including dataWindow origin, on ingestion services to identify anomalous inputs.
- Monitor crash telemetry from creative tools, transcoders, and thumbnailers that link OpenEXRUtil.
- Track outbound traffic from EXR-processing hosts for unexpected data transfers following file parsing.
How to Mitigate CVE-2026-59189
Immediate Actions Required
- Upgrade OpenEXR to version 3.3.13 or 3.4.13, which contain the corrected row() implementations.
- Rebuild and redeploy any downstream applications, plugins, and container images that statically link OpenEXRUtil.
- Restrict processing of untrusted EXR files until patched binaries are in place across the pipeline.
Patch Information
The fix is delivered through the following upstream commits and advisory:
- GitHub Commit #37f03b6
- GitHub Commit #55b7958
- GitHub Commit #aef0222
- GitHub Security Advisory GHSA-hwmv-39v6-739m
The patched code replaces _base with _sampleListPointers in ImfDeepImageChannel.h and with _pixels in ImfFlatImageChannel.h, aligning row(r) with its documented 0-based semantics.
Workarounds
- Reject or normalize EXR files whose dataWindow.min is non-zero at the ingestion boundary.
- Sandbox EXR-processing workers with seccomp, AppArmor, or containers to contain crashes and limit information disclosure.
- Avoid calling TypedDeepImageChannel::row() or TypedFlatImageChannel::row() in application code until the upgrade is complete; prefer at(x, y) with absolute coordinates.
# Verify installed OpenEXR version and upgrade
pkg-config --modversion OpenEXR
# Example: build patched OpenEXR 3.4.13 from source
git clone --branch v3.4.13 https://github.com/AcademySoftwareFoundation/openexr.git
cmake -S openexr -B openexr/build -DCMAKE_BUILD_TYPE=Release
cmake --build openexr/build --parallel
sudo cmake --install openexr/build
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

