PoC Archive PoC Archive
Important CVE-2026-5201 patched

gdk-pixbuf JPEG Loader Heap Buffer Overflow — CVE-2026-5201

by Kağan Çapar (GitHub: kagancapar) — acknowledged by Red Hat · 2026-07-05

CVSS 7.5/10
Severity
Important
CVE
CVE-2026-5201
Category
binary
Affected product
gdk-pixbuf (GNOME image loading library), JPEG loader (io-jpeg.c)
Affected versions
All gdk-pixbuf versions prior to commit 6cce9311e70b969cbcc6e3e1e74ae1756ed02d5b (fixed in 2.44.6); confirmed vulnerable on gdk-pixbuf 2.42.10 (Ubuntu 24.04 LTS) and 2.44.5
Disclosed
2026-07-05
Patch status
patched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-04
Author / ResearcherKağan Çapar (GitHub: kagancapar) — acknowledged by Red Hat
CVE / AdvisoryCVE-2026-5201
Categorybinary
SeverityImportant
CVSS Score7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H, as stated in source repository / Red Hat advisory)
StatusPoC
Tagsgdk-pixbuf, jpeg, libjpeg, heap-overflow, gnome, gtk, linux-desktop, cwe-122, vtable-hijack
RelatedCVE-2017-2862 (same bug class, prior gdk-pixbuf JPEG null_convert overflow)

Affected Target

FieldValue
Software / Systemgdk-pixbuf (GNOME image loading library), JPEG loader (io-jpeg.c)
Versions AffectedAll gdk-pixbuf versions prior to commit 6cce9311e70b969cbcc6e3e1e74ae1756ed02d5b (fixed in 2.44.6); confirmed vulnerable on gdk-pixbuf 2.42.10 (Ubuntu 24.04 LTS) and 2.44.5
Language / PlatformPython (JPEG reproducer generator), C (crash/exploitation PoCs, ASan); target is native C (gdk-pixbuf/libjpeg) on Linux
Authentication RequiredNo
Network Access RequiredNo (local file processing); Red Hat’s CVSS vector marks AV:N/UI:N reflecting automated/server-side image processing scenarios

Summary

gdk-pixbuf’s direct JPEG loading path (gdk_pixbuf__jpeg_image_load / gdk_pixbuf__real_jpeg_image_load in io-jpeg.c) allocates the output pixel buffer based on the expected number of color components (3 for RGB, 4 for CMYK) without validating that libjpeg’s actual output_components value matches. A crafted 122-byte JPEG that declares 9 components in its SOF10 header but only scans 3 in the SOS marker causes libjpeg to decode 9 bytes per pixel into a buffer sized for 3, an approximately 49KB heap overflow for the PoC’s dimensions. This repository includes a Python reproducer that generates the malicious JPEG, C crash-test/AddressSanitizer harnesses that demonstrate the overflow and resulting corruption of adjacent GObject vtable pointers, and detailed bilingual (English/Turkish) writeups covering root cause, exploitation primitives (including a demonstrated 32-bit RCE via dispose() function-pointer hijack and an ASLR-bypass technique), and the official upstream fix.


Vulnerability Details

Root Cause

In gdk-pixbuf/io-jpeg.c, the direct file-loading path allocates the pixbuf using cinfo->out_color_components (line ~633) to decide the buffer’s channel count, but does not check cinfo->output_components against the allowed values (3, 4, or 1-for-grayscale) before calling jpeg_read_scanlines() (line ~696), which writes output_components bytes per pixel as reported by libjpeg. The incremental loader path (GdkPixbufLoader) already contains this exact validation (line ~1142), but it is missing from the direct-loading path, creating an inconsistency where the same malformed JPEG is safely rejected by one path and triggers a heap overflow through the other.

Attack Vector

  1. Attacker crafts a 122-byte JPEG with a SOF10 (arithmetic sequential DCT) header declaring 9 color components but a SOS marker that only scans 3 of them, sized 8224x1 pixels.
  2. Victim application calls gdk_pixbuf_new_from_file() (or any API using the direct-loading path) on the crafted file — e.g., an image viewer, file manager, or automated/server-side image-processing pipeline.
  3. gdk-pixbuf allocates an undersized buffer (8224 x 3 = 24,672 bytes) based on the RGB/CMYK assumption.
  4. libjpeg’s null_convert() writes 8224 x 9 = 74,016 bytes into that buffer — a 49,344-byte overflow — corrupting adjacent heap memory, including a neighboring GObject’s g_class vtable pointer.
  5. When g_object_unref() is later called, it dereferences the corrupted vtable pointer, leading to a crash (64-bit) or, as demonstrated in the repo, a dispose() function-pointer hijack enabling arbitrary code execution (32-bit, and shown as achievable via partial-pointer-overwrite/ASLR-bypass techniques on 64-bit primitives).

Impact

Reliable (100%) crash/denial of service in any application using gdk_pixbuf_new_from_file(); heap corruption of adjacent GObject structures; demonstrated code execution on 32-bit Linux via GObject vtable dispose() hijack, with the repo documenting (but not weaponizing end-to-end) the additional primitives — deterministic heap layout and partial-pointer ASLR bypass — relevant to 64-bit exploitation.


Environment / Lab Setup

Target:   Ubuntu 24.04.1 LTS, gdk-pixbuf 2.42.10+dfsg-3ubuntu3.2,
          libjpeg-turbo 2.1.5 (libjpeg.so.8.2.2), GCC 13.3.0, glibc 2.39
Attacker: Python 3 (reproducer generator), GCC + AddressSanitizer,
          pkg-config with gdk-pixbuf-2.0 development headers

Proof of Concept

PoC Script

See reproducer/craft_cve_2026_5201.py, reproducer/cve_2026_5201.jpg, poc/crash_test.c, poc/rce_32bit.c, poc/rce_shell.c, poc/aslr_bypass.c, poc/find_dispose.c, poc/heap_analysis.c, poc/pixel_control_test.c, poc/analyze_jpeg.py, patch/0001-io-jpeg-Fix-heap-buffer-overflow.patch, and the full writeups in writeup-en/ and writeup-tr/ in this folder.

1
2
3
4
5
python3 reproducer/craft_cve_2026_5201.py

gcc -o crash_test poc/crash_test.c \
    $(pkg-config --cflags --libs gdk-pixbuf-2.0) -fsanitize=address -g
./crash_test cve_2026_5201.jpg

craft_cve_2026_5201.py builds the minimal malformed JPEG (SOF10 with 9 declared components, SOS scanning only 3). crash_test.c loads the file via both gdk_pixbuf_new_from_file() (vulnerable direct path) and GdkPixbufLoader (safe incremental path) to demonstrate the discrepancy; the other poc/*.c files (rce_32bit.c, rce_shell.c, aslr_bypass.c, find_dispose.c) further explore the GObject vtable corruption and its exploitation into RCE primitives.


Detection & IOCs

Signs of compromise:

  • Applications using gdk_pixbuf_new_from_file() crashing while loading a JPEG file
  • Crash reports/tombstones referencing null_convert, sep_upsample, or g_object_unref shortly after JPEG loading
  • JPEG files with a SOF header declaring more color components than are present in the corresponding SOS scan

Remediation

ActionDetail
Primary fixUpdate gdk-pixbuf to 2.44.6 or later, which includes the output_components validation fix (commit 6cce9311e70b969cbcc6e3e1e74ae1756ed02d5b, matching the included patch/0001-io-jpeg-Fix-heap-buffer-overflow.patch)
Interim mitigationAvoid processing untrusted JPEG files via direct-loading APIs (gdk_pixbuf_new_from_file()); where possible, route untrusted images through sandboxed/incremental loaders or a separately-patched libjpeg wrapper until updated

References


Notes

Mirrored from https://github.com/kagancapar/CVE-2026-5201 on 2026-07-05.