NIST deprecates RSA-2048 from 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
HIGH severity

OpenEXR Heap-Based Buffer Overflow in Deep Scanline Parsing via Forged Unpacked SizeGHSA-h45x-qhg2-q375

HIGHFix: AcademySoftwareFoundation/openexr@916cc72

GHSA-h45x-qhg2-q375 is a high-severity (CVSS 7.8) CWE-122 vulnerability in openexr. A fix is available for openexr — see the affected versions and patch details below.

Also known asCVE-2025-48071PYSEC-2026-1747
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Nov 11, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • A successful exploit gives an attacker total control of the affected component, not partial access.

Exploitation and automatability from CISA’s SSVC triage for GHSA-h45x-qhg2-q375.

EPSS Exploitation Probability

via FIRST.org ↗
0.4%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs34th percentile — riskier than 34% of all scored CVEsHighest risk
0.00%0.30%0.59%0.89%0.0%0.4%May 26Sep 26Nov 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

Where this sits among everything scored

Real-World Exposure

1 pkg affected
🐍openexr

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Summary

The OpenEXRCore code is vulnerable to a heap-based buffer overflow during a write operation when decompressing ZIPS-packed deep scan-line EXR files with a maliciously forged chunk header.

Details

When parsing STORAGE_DEEP_SCANLINE chunks from an EXR file, the following code (from src/lib/OpenEXRCore/chunk.c) is used to extract the chunk information:


if (part->storage_mode == EXR_STORAGE_DEEP_SCANLINE)
// SNIP...
        cinfo->sample_count_data_offset = dataoff;
        cinfo->sample_count_table_size  = (uint64_t) ddata[0];
        cinfo->data_offset              = dataoff + (uint64_t) ddata[0];
        cinfo->packed_size              = (uint64_t) ddata[1];
        cinfo->unpacked_size            = (uint64_t) ddata[2];
// SNIP...

By storing this information, the code that will later decompress and reconstruct the chunk bytes, will know how much space the uncompressed data will occupy.

This size is carried along in the chain of decoding/decompression until the undo_zip_impl function in src/lib/OpenEXRCore/internal_zip.c:

static exr_result_t
undo_zip_impl (
    exr_decode_pipeline_t* decode,
    const void*            compressed_data,
    uint64_t               comp_buf_size,
    void*                  uncompressed_data,
    uint64_t               uncompressed_size,
    void*                  scratch_data,
    uint64_t               scratch_size)
{
    size_t       actual_out_bytes;
    exr_result_t res;

    if (scratch_size < uncompressed_size) return EXR_ERR_INVALID_ARGUMENT;

    res = exr_uncompress_buffer (
        decode->context,
        compressed_data,
        comp_buf_size,
        scratch_data,
        scratch_size,
        &actual_out_bytes);

    if (res == EXR_ERR_SUCCESS)
    {
        decode->bytes_decompressed = actual_out_bytes;
        if (comp_buf_size > actual_out_bytes)
            res = EXR_ERR_CORRUPT_CHUNK;
        else
            internal_zip_reconstruct_bytes (
                uncompressed_data, scratch_data, actual_out_bytes);
    }

    return res;
}

The uncompressed_size comes from the unpacked_size extracted earlier, and the uncompressed_data is a buffer allocated by making space for the size "advertised" in the chunk information.

However, scratch_data and actual_out_bytes will contain, after decompression, the uncompressed data and its size, respectively.

The vulnerability lies in the fact that the undo_zip_impl function lacks code to check whether actual_out_bytes is greater than uncompressed_size.

The effect is that, by setting the unpacked_size in the chunk header smaller than the actual chunk decompressed data, it is possible - in the internal_zip_reconstruct_bytes function - to overflow past the boundaries of a heap chunk.

PoC

NOTE: you can download the heap_overflow.exr file from this link:

https://github.com/ShielderSec/poc/tree/main/CVE-2025-48071

  1. Compile the exrcheck binary in a macOS or GNU/Linux machine with ASAN.
  2. Open the heap_overflow.exr file with the following command:
exrcheck heap_overflow.exr
  1. Notice that exrcheck crashes with an ASAN stack-trace. image

Impact

An attacker might exploit this vulnerability by feeding a maliciously crafted file to a program that uses the OpenEXR libraries, thus gaining the capability to write an arbitrary amount of bytes in the heap. This could potentially result in code execution in the process.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIopenexr≥ 3.3.0&&< 3.3.33.3.3pip install --upgrade 'openexr==3.3.3'

Affected Products

1 product · 1 configurations
Application
openexropenexr
≥ 3.3.0 && < 3.3.3
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for openexr, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update openexr to 3.3.3 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-h45x-qhg2-q375 is resolved across your whole dependency graph.

  3. Workarounds

    Stop feeding it untrusted input: reject or quarantine files and payloads from unverified sources until you can upgrade, restrict accepted formats to the ones you actually need, and run the parsing or decoding step in a least-privileged sandbox or short-lived worker so a crash or corrupted read cannot reach the rest of the process.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatImportant

No Red Hat products or offerings are affected by this vulnerability. This vulnerability should be considered Important rather than Moderate because it allows a heap-based buffer overflow during decompression of ZIPS-packed deep scan-line EXR files with a forged chunk header, which directly impacts memory safety. Heap…

Workaround published by Red Hat
Mitigation for this issue is either not available or the currently available options do not meet the Red Hat Product Security criteria comprising ease of use and deployment, applicability to widespread installation base or stability.
Source: Red Hat security advisory for GHSA-h45x-qhg2-q375 (CC BY 4.0)

Frequently Asked Questions

### Summary The OpenEXRCore code is vulnerable to a heap-based buffer overflow during a write operation when decompressing ZIPS-packed deep scan-line EXR files with a maliciously forged chunk header. ### Details When parsing `STORAGE_DEEP_SCANLINE` chunks from an EXR file, the following code (from `src/lib/OpenEXRCore/chunk.c`) is used to extract the chunk information: ```cpp if (part->storage_mode == EXR_STORAGE_DEEP_SCANLINE) // SNIP... cinfo->sample_count_data_offset = dataoff; cinfo->sample_count_table_size = (uint64_t) ddata[0]; cinfo->data_offset
O3 Security · Impact-Aware SCA

Is GHSA-h45x-qhg2-q375 in your dependencies?

Find it across PyPI, including transitive dependencies.

OpenEXR Heap-Based Buffer Overflow in Deep Scanline…