## https://sploitus.com/exploit?id=E83D35A6-9C47-58A3-80BC-279B00AB3E86
# CVE-2026-5201
**Heap-based buffer overflow in gdk-pixbuf JPEG loader**
Hi, I'm [Kağan Çapar](https://github.com/kagancapar). I discovered a heap-based buffer overflow vulnerability in gdk-pixbuf's JPEG image loader that affects virtually all Linux desktop environments. The vulnerability was assigned **CVE-2026-5201** and acknowledged by [Red Hat](https://access.redhat.com/security/cve/CVE-2026-5201) with a CVSS score of **7.5 (Important)**.
This repository contains my full analysis, a reproducer I wrote from scratch, and the crash evidence from a live Ubuntu 24.04 LTS system.
| | |
|---|---|
| **CVE** | [CVE-2026-5201](https://vulners.com/cve/CVE-2026-5201) |
| **CWE** | [CWE-122](https://cwe.mitre.org/data/definitions/122.html) — Heap-based Buffer Overflow |
| **CVSS v3** | **7.5** (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H) |
| **Affected** | gdk-pixbuf (all versions before fix) |
| **Vendor** | GNOME |
| **Fix** | [gdk-pixbuf@6cce931](https://gitlab.gnome.org/GNOME/gdk-pixbuf/-/commit/6cce9311e70b969cbcc6e3e1e74ae1756ed02d5b) |
| **Tracker** | [GNOME #304](https://gitlab.gnome.org/GNOME/gdk-pixbuf/-/issues/304) |
| **Bugzilla** | [Red Hat #2453291](https://bugzilla.redhat.com/show_bug.cgi?id=2453291) |
## Summary
I found a heap-based buffer overflow in gdk-pixbuf's JPEG image loader (`io-jpeg.c`). The direct file loading path (`gdk_pixbuf__jpeg_image_load`) does not validate the number of color components before allocating a pixel buffer. A specially crafted 122-byte JPEG with 9 components declared in the SOF header but only 3 scanned in SOS causes gdk-pixbuf to allocate a buffer for 3 channels while libjpeg writes 9 channels per pixel — resulting in a heap overflow of up to ~41 KB of attacker-controlled data.
The incremental loader path already had this exact validation, but it was missing from the direct loading path.
## Impact
- **Denial of Service**: 100% reliable crash on any application using `gdk_pixbuf_new_from_file()`
- **Heap corruption**: GObject vtable pointer (`g_class`) overwritten with pixel data
- **Code execution**: Demonstrated on 32-bit Linux via vtable hijack
- **Affected systems**: All Linux desktops — Ubuntu, Fedora, Debian, Arch, RHEL 7–10
## Affected Red Hat Products
| Product | Component | Status |
|---------|-----------|--------|
| Red Hat Enterprise Linux 10 | gdk-pixbuf2 | Affected |
| Red Hat Enterprise Linux 10 | loupe | Affected |
| Red Hat Enterprise Linux 10 | snapshot | Affected |
| Red Hat Enterprise Linux 9 | gdk-pixbuf2 | Affected |
| Red Hat Enterprise Linux 8 | gdk-pixbuf2 | Affected |
| Red Hat Enterprise Linux 7 | gdk-pixbuf2 | Affected |
## Root Cause
In `gdk-pixbuf/io-jpeg.c`, the function `gdk_pixbuf__jpeg_image_load()`:
**1. Undersized allocation** ([line 633](https://gitlab.gnome.org/GNOME/gdk-pixbuf/-/blob/master/gdk-pixbuf/io-jpeg.c#L633)):
```c
pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
cinfo->out_color_components == 4 ? TRUE : FALSE,
8, cinfo->output_width, cinfo->output_height);
```
**2. Oversized write** ([line 696](https://gitlab.gnome.org/GNOME/gdk-pixbuf/-/blob/master/gdk-pixbuf/io-jpeg.c#L696)):
```c
jpeg_read_scanlines(cinfo, lines, cinfo->rec_outbuf_height);
// writes output_components (9) bytes per pixel into a 3-byte buffer
```
**3. Missing validation** — the incremental loader already checks `output_components` at [line 1142](https://gitlab.gnome.org/GNOME/gdk-pixbuf/-/blob/master/gdk-pixbuf/io-jpeg.c#L1142), but this check was absent from the direct path.
## Reproduction
### Generate the reproducer
```bash
python3 reproducer/craft_cve_2026_5201.py
```
This creates a 122-byte JPEG file with 9 components in the SOF10 header and only 3 scanned in SOS.
### Trigger the crash
```bash
# Compile
gcc -o crash_test reproducer/crash_test.c \
$(pkg-config --cflags --libs gdk-pixbuf-2.0) -fsanitize=address -g
# Run
./crash_test cve_2026_5201.jpg
```
### Expected output (AddressSanitizer)
```
==PID==ERROR: AddressSanitizer: SEGV on unknown address 0x52b000020006
==PID==The signal is caused by a WRITE memory access.
#0 libjpeg.so.8 (null_convert)
#1 libjpeg.so.8 (sep_upsample)
#2 libjpeg.so.8 (process_data_context_main)
#3 libjpeg.so.8 jpeg_read_scanlines
#4 libgdk_pixbuf-2.0.so.0 (JPEG loader)
#5 libgdk_pixbuf-2.0.so.0 gdk_pixbuf_new_from_file
```
### GDB output (without ASAN)
```
Program received signal SIGSEGV, Segmentation fault.
g_type_check_instance_is_fundamentally_a ()
→ g_object_unref()
→ gdk_pixbuf_new_from_file()
rax = 0x808080808080ffff ← corrupted GObject vtable pointer
```
## Fix
The fix adds the same `output_components` validation that already exists in the incremental loader:
```c
jpeg_start_decompress(cinfo);
if (cinfo->output_components != 3 && cinfo->output_components != 4 &&
!(cinfo->output_components == 1 &&
cinfo->out_color_space == JCS_GRAYSCALE)) {
g_set_error(error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
"Unsupported number of color components (%d)",
cinfo->output_components);
goto out;
}
```
Applied in [gdk-pixbuf@6cce931](https://gitlab.gnome.org/GNOME/gdk-pixbuf/-/commit/6cce9311e70b969cbcc6e3e1e74ae1756ed02d5b).
## Tested Environment
| | |
|---|---|
| OS | Ubuntu 24.04.1 LTS |
| gdk-pixbuf | 2.42.10+dfsg-3ubuntu3.2 |
| libjpeg | libjpeg-turbo 2.1.5 (libjpeg.so.8.2.2) |
| GCC | 13.3.0 |
## References
- https://vulners.com/cve/CVE-2026-5201
- https://nvd.nist.gov/vuln/detail/CVE-2026-5201
- https://gitlab.gnome.org/GNOME/gdk-pixbuf/-/issues/304
- https://access.redhat.com/security/cve/CVE-2026-5201
- https://bugzilla.redhat.com/show_bug.cgi?id=2453291
## Historical Precedent
[CVE-2017-2862](https://nvd.nist.gov/vuln/detail/CVE-2017-2862) (Cisco Talos TALOS-2017-0366) — CVSS 8.8 — same `null_convert` buffer mismatch bug class in gdk-pixbuf, classified as Remote Code Execution.
## Credit
**Kağan Çapar** — [GitHub](https://github.com/kagancapar) · [LinkedIn](https://linkedin.com/in/kagancapar) · [X](https://x.com/kagancapar)
*Acknowledged by Red Hat in the [CVE-2026-5201 advisory](https://access.redhat.com/security/cve/CVE-2026-5201).*