---
id: "CVE-2026-91186"
kind: "vulnerability"
aliases: ["CVE-2026-91186"]
title: "PNG decoder: a repeated IHDR chunk causes out-of-bounds memory writes"
severity: "high"
cvss: 8.4
epss: null
exploited: false
status: "open"
category: "package"
products: [{"name": "guix", "fixed": ["6.5.2.202603"], "affected": "<= 6.5.1.202602a", "ecosystem": "vendor"}]
ecosystems: []
tags: ["eclipse-threadx", "embedded", "guix", "heap-overflow", "image-processing", "package", "png-decoder", "rtos", "self-hosted"]
not_affected_if: ["no-png-decoding", "software-decoder-disabled", "trusted-images-only", "trusted-input-only"]
published_at: "2026-10-20T15:17:36+00:00"
first_seen_at: "2026-10-23T21:57:20+00:00"
updated_at: "2026-10-25T03:28:07+00:00"
sources: [{"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-91186", "first_seen_at": "2026-10-23T21:57:20+00:00"}, {"source": "analyst", "url": null, "first_seen_at": "2026-10-25T03:28:07+00:00"}]
---

# PNG decoder: a repeated IHDR chunk causes out-of-bounds memory writes

GUIX (Eclipse ThreadX) PNG decoder accepts a second IHDR after IDAT, changing dimensions after the buffer is allocated; the row-unfilter pass then writes past the end of the heap buffer. Reporter confirmed with a 94-byte file; vendor claims no code execution. Affects products on GUIX <= 6.5.1.202602a that decode PNGs they did not produce (removable media, updates, network); decoder is on by default. Builds that disable the software decoder or load only trusted images can skip it.

_Summary, check and fix written by a model from the sources; labelled as such._

## Affected

- vendor:guix affected <= 6.5.1.202602a fixed 6.5.2.202603

## How to check

Check the GUIX version in your firmware or source tree. Any release up to and including 6.5.1.202602a is affected. Check that GX_DISABLE_SOFTWARE_DECODER_SUPPORT is not defined, since the software PNG decoder is on by default. Check whether the app decodes PNGs from untrusted sources such as removable media, updates or network.

## Fix

Upgrade Eclipse ThreadX GUIX to 6.5.2.202603 (no backport to 6.4.x). The fix rejects a second IHDR or PLTE and an IDAT before IHDR, and checks in unfilter that the walk fits the buffer.

## Timeline

- 2026-10-23T21:57:20+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-91186
- 2026-10-25T03:28:07+00:00 analyst — Read vendor GHSA-gx8f-4rpc-4fjw (Eclipse ThreadX GUIX): <=6.5.1.202602a affected, fixed 6.5.2.202603. No exploitation or public PoC claimed (reporter had a 94-byte repro, not published). Vendor CVSS3.1 7.8 local/UI-required; CNA CVSS4 8.4. No flag for who_is_affected, so it is folded into the summary.

## Documents

- [advisory] GHSA-gx8f-4rpc-4fjw: GUIX PNG decoder duplicate IHDR heap OOB write https://github.com/eclipse-threadx/guix/security/advisories/GHSA-gx8f-4rpc-4fjw
- [describes] CVE Record CVE-2026-91186 https://www.cve.org/CVERecord?id=CVE-2026-91186

## From the sources

The PNG chunk reader has no notion of chunk ordering. It records whether an IDAT has been seen and whether a tRNS has already supplied transparency, but nothing prevents an IHDR being read a second time.



A PNG carries exactly one IHDR and it is the first chunk. A file that places a second one after IDAT rewrites the image width, height, bit depth and pixel depth *after* the decoded-data buffer has already been allocated and filled from the original values. The pass that reverses the PNG row filters then derives its own extent from the new dimensions and walks the old allocation, moving image bytes past the end of it.



The buffer is allocated by GUIX rather than supplied by the caller, so the application has no way to size it defensively. The decoder is compiled in by default.

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
