CVE-2026-67549 Overview
CVE-2026-67549 is a heap out-of-bounds write vulnerability in OpenImageIO, a toolset used across VFX and animation pipelines for reading, writing, and manipulating image files. The flaw affects versions prior to 3.1.16.0 and is triggered when the library processes a crafted 1-bit contiguous CMYK TIFF file. The parser exposes the image through a native uint1ImageSpec, causing callers to allocate a bit-packed buffer. The TIFF reader then writes 8-bit expanded values into that smaller buffer, corrupting adjacent heap memory.
Critical Impact
A crafted TIFF file can trigger heap memory corruption in any application that uses OpenImageIO to decode untrusted images, enabling denial of service and potential code execution.
Affected Products
- OpenImageIO versions prior to 3.1.16.0
- Applications embedding OpenImageIO for TIFF decoding
- VFX and animation pipelines processing untrusted CMYK TIFF assets
Discovery Timeline
- 2026-09-18 - CVE-2026-67549 published to the National Vulnerability Database (NVD)
- 2026-09-24 - Last updated in NVD database
Technical Details for CVE-2026-67549
Vulnerability Analysis
The vulnerability resides in src/tiff.imageio/tiffinput.cpp, specifically in TIFFInput::read_native_scanline_locked() and TIFFInput::bit_convert(). When a TIFF file uses PHOTOMETRIC_SEPARATED with 1-bit CMYK samples, OpenImageIO exposes the image through a native uint1ImageSpec. Callers observing that spec allocate a compact bit-packed destination buffer sized for 1-bit samples.
Despite the packed destination, read_native_scanline_locked() calls bit_convert() with an 8-bit output width. Each 1-bit source value expands to a full byte and is written into the smaller destination, overflowing the heap allocation. The result is heap memory corruption classified as [CWE-122] Heap-based Buffer Overflow.
Root Cause
The root cause is an inconsistency between the buffer size advertised through the ImageSpec and the byte width actually produced by the bit-expansion routine. The m_photometric == PHOTOMETRIC_SEPARATED branch was not considered when deciding whether to write into caller memory or into an internal scratch buffer. Only the separate-plane case (m_separate) routed output through scratch, leaving the contiguous CMYK code path writing directly into an undersized caller buffer.
Attack Vector
Exploitation requires an application to decode an attacker-supplied TIFF file with OpenImageIO. This includes render farms, asset ingest tools, thumbnailers, and web services that process user-submitted imagery. No authentication is required, but user interaction to open or import the file is typically needed.
}
// Handle less-than-full bit depths
+ bool use_scratch_dest = m_separate
+ || (m_photometric == PHOTOMETRIC_SEPARATED
+ && !m_raw_color);
if (m_bitspersample < 8) {
// m_scratch now holds nvals n-bit values, contig or separate
m_scratch2.resize(input_bytes);
m_scratch.swap(m_scratch2);
for (int c = 0; c < planes; ++c) /* planes==1 for contig */
bit_convert(m_separate ? m_spec.width : nvals,
&m_scratch2[plane_bytes * c], m_bitspersample,
- m_separate
+ use_scratch_dest
? &m_scratch[plane_bytes * c]
: (unsigned char*)data.data() + plane_bytes * c,
8);
Source: GitHub Commit 6e9b86e. The patch routes 1-bit contiguous CMYK output through the internal m_scratch buffer instead of writing directly into the caller-supplied bit-packed destination, preventing the overflow.
Detection Methods for CVE-2026-67549
Indicators of Compromise
- Crashes or abort signals in processes linking libOpenImageIO when reading TIFF inputs
- Heap corruption warnings from allocators such as glibc (malloc_consolidate, double free or corruption) during image decoding
- TIFF assets in ingest pipelines with PhotometricInterpretation = 5 (CMYK) and BitsPerSample = 1
- AddressSanitizer or Valgrind reports pointing to TIFFInput::bit_convert frames
Detection Strategies
- Inventory hosts and containers running OpenImageIO builds older than 3.1.16.0, including bundled copies inside DCC applications and render nodes.
- Scan TIFF ingest queues for files with PHOTOMETRIC_SEPARATED and BitsPerSample=1 and quarantine them for review.
- Enable process crash telemetry on renderers, thumbnail services, and asset pipelines to catch anomalous termination during image parsing.
Monitoring Recommendations
- Forward endpoint and workload crash events, dmesg segfault records, and container OOM/abort signals to a centralized data lake for correlation.
- Alert on repeated crashes of the same image-processing binary across multiple hosts, which can indicate a malicious asset traversing a pipeline.
- Monitor outbound network activity from render nodes and asset services after suspected exploitation, since successful memory corruption may lead to secondary payloads.
How to Mitigate CVE-2026-67549
Immediate Actions Required
- Upgrade all OpenImageIO installations to version 3.1.16.0 or later.
- Rebuild and redeploy applications that statically link OpenImageIO after upgrading the library.
- Restrict acceptance of externally supplied TIFF files in automated ingestion pipelines until patches are in place.
- Isolate render farms and asset-conversion services from direct internet exposure where possible.
Patch Information
The fix is included in OpenImageIO Release v3.1.16.0 and merged via GitHub Pull Request #5296. Full details are documented in GitHub Security Advisory GHSA-3wxw-rqhw-j2w4. The patch in commit 6e9b86e redirects sub-8-bit contiguous CMYK output into an internal scratch buffer.
Workarounds
- Pre-filter TIFF inputs and reject files where PhotometricInterpretation equals 5 (CMYK) and BitsPerSample equals 1.
- Convert untrusted TIFF assets to a safe intermediate format such as PNG using a hardened, sandboxed tool before passing them to OpenImageIO.
- Run image-processing workloads in restricted containers with seccomp and no-new-privileges to limit the blast radius of memory corruption.
# Reject 1-bit CMYK TIFFs at the ingest boundary using tiffinfo
for f in /ingest/*.tif; do
photo=$(tiffinfo "$f" 2>/dev/null | awk -F': ' '/Photometric/ {print $2}')
bps=$(tiffinfo "$f" 2>/dev/null | awk -F': ' '/Bits\/Sample/ {print $2}')
if [ "$photo" = "separated" ] && [ "$bps" = "1" ]; then
mv "$f" /quarantine/
fi
done
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

