CVE-2026-59981 Overview
CVE-2026-59981 is an out-of-bounds read vulnerability [CWE-125] in the OpenEXR reference implementation, which is widely used across the motion picture and visual effects industry. The flaw resides in the OpenEXRUtil library, specifically in the SampleCountChannel::row() API used to access deep image sample counts. When a deep EXR file declares a non-zero dataWindow origin, the row() accessor returns a pointer outside the allocated sample-count buffer. Applications that parse attacker-controlled deep EXR files can crash or leak adjacent heap memory as sample-count values. Affected releases include versions through 3.2.10, 3.3.0 through 3.3.12, and 3.4.0 through 3.4.13. Fixed versions are 3.2.11, 3.3.13, and 3.4.14.
Critical Impact
An attacker-crafted deep EXR file can trigger an out-of-bounds read, resulting in process crash or disclosure of adjacent heap memory when opened by a vulnerable application.
Affected Products
- OpenEXR versions through 3.2.10
- OpenEXR versions 3.3.0 through 3.3.12
- OpenEXR versions 3.4.0 through 3.4.13
Discovery Timeline
- 2026-08-25 - CVE-2026-59981 published to the National Vulnerability Database
- 2026-08-25 - Last updated in NVD database
Technical Details for CVE-2026-59981
Vulnerability Analysis
The vulnerability arises from a coordinate model conflict inside the OpenEXRUtil library. The SampleCountChannel::row() accessor is documented as 0-based, meaning callers pass row indices starting from zero. Internally, however, row() computes its address from a _base pointer that has been pre-offset to represent absolute pixel coordinates. When dataWindow.min is non-zero, these two coordinate models collide.
For a deep image whose data window declares a large negative vertical origin, the call row(0) resolves to an address far outside the allocated sample-count buffer. Any read through that pointer accesses memory the library does not own, which produces a crash or, under a shaped heap layout, returns adjacent allocations as sample-count values.
Root Cause
The underlying defect is the reuse of an absolute-coordinate _base pointer inside a 0-based accessor. The internal buffer pointer and the caller-facing index scheme use different origins, so arithmetic on them is not safe unless dataWindow.min is zero. The library never re-anchors the base pointer for the 0-based API surface.
Attack Vector
Exploitation requires the victim to open a malicious deep EXR file with a vulnerable application built against OpenEXRUtil. This is a passive, user-interaction attack path common to media pipelines, render farms, and asset ingestion tools that automatically parse untrusted image files.
// 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 ();
}
The fix replaces the pre-offset _base pointer with _sampleListPointers (deep images) and _pixels (flat images), both of which are anchored at the allocation origin. This restores agreement between the 0-based caller API and the internal pointer arithmetic. Source: GitHub Commit 37f03b6.
Detection Methods for CVE-2026-59981
Indicators of Compromise
- Unexpected crashes in applications linked against OpenEXRUtil when processing deep EXR files.
- Deep EXR files with a dataWindow.min containing large negative vertical coordinates.
- Anomalous sample-count values or malformed pixel data produced when opening third-party EXR assets.
Detection Strategies
- Inventory software linked against OpenEXR shared libraries and identify versions matching the affected ranges.
- Scan EXR files in ingestion pipelines and flag those whose dataWindow origin is non-zero, especially with negative values.
- Enable AddressSanitizer or similar runtime checks in build pipelines and CI to surface out-of-bounds reads in SampleCountChannel::row().
Monitoring Recommendations
- Monitor render farm and content-ingestion services for repeated segmentation faults or unexpected worker restarts tied to EXR parsing.
- Log EXR file provenance and hash values in asset management systems to enable retrospective triage.
- Alert on outbound data flows from processes that handle untrusted EXR content, which may indicate memory disclosure attempts.
How to Mitigate CVE-2026-59981
Immediate Actions Required
- Upgrade OpenEXR to 3.2.11, 3.3.13, or 3.4.14 depending on the deployed release branch.
- Rebuild and redistribute any applications, plugins, or containers that statically link the affected OpenEXRUtil code.
- Restrict ingestion of EXR files to trusted sources until patched binaries are deployed across the pipeline.
Patch Information
The fix is committed upstream in the AcademySoftwareFoundation OpenEXR repository. Relevant references include GitHub Commit 37f03b6, GitHub Commit 55b7958, GitHub Commit aef0222, and GitHub Security Advisory GHSA-m799-ffc3-8pxc. The patches replace the offset _base pointer with the correctly anchored _sampleListPointers and _pixels members inside ImfDeepImageChannel.h and ImfFlatImageChannel.h.
Workarounds
- Reject or normalize deep EXR files whose dataWindow.min is non-zero before passing them to OpenEXRUtil.
- Run EXR parsing in a sandboxed process with restricted memory access and automatic crash recovery.
- Isolate untrusted EXR processing on dedicated hosts with no access to sensitive tenant data.
# Verify installed OpenEXR version and upgrade to a fixed release
pkg-config --modversion OpenEXR
# Example: rebuild against a fixed release
git clone https://github.com/AcademySoftwareFoundation/openexr.git
cd openexr
git checkout v3.4.14
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --target install
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

