PixelSmash: one video file that puts FFmpeg-powered servers at risk
CVE-2026-8461 is a patched heap overflow in FFmpeg's MagicYUV decoder — reliable DoS, conditional RCE, and hiding in software you didn't know shipped FFmpeg.
FFmpeg's libavcodec is the quiet engine behind a staggering amount of the internet's media handling — media servers, file-sync previews, desktop thumbnailers, NAS boxes, and AI data pipelines all lean on it. So when JFrog disclosed CVE-2026-8461, nicknamed "PixelSmash," a heap out-of-bounds write in FFmpeg's MagicYUV decoder, the bug itself was ordinary but the blast radius was not.
Here's the honest version: it's a reliable denial-of-service against anything that auto-decodes untrusted video, and a conditional remote-code-execution in the wrong (but common enough) conditions. It is not on CISA's KEV list, EPSS is low (~0.4%), and there's no public weaponized exploit as of this writing. The real work isn't deciding whether to patch — it's finding every embedded copy of FFmpeg.
What actually breaks
MagicYUV is a fast lossless codec whose decoder splits each frame into horizontal slices. The flaw is a rounding mismatch: with chroma-subsampled formats (like YUV420P), the frame allocator and the per-slice decoder compute the chroma plane height differently. Feed the decoder an odd slice_height and the second slice's write base lands exactly one row past the heap buffer — a classic out-of-bounds write (CWE-787).
Because the overflowing bytes are attacker-controlled pixel data, this isn't only a crash. The bytes after the buffer can include an AVBuffer struct; overwrite its free function pointer and its argument, and FFmpeg's normal frame cleanup (av_buffer_unref()) turns into an attacker-controlled call. That's the path from "out-of-bounds write" to "code execution."
Why it's a big deal: FFmpeg is everywhere
The trigger is a crafted AVI, MKV, or MOV (notably not plain MP4) carrying a MagicYUV stream. The CVSS vector carries UI:R — "user interaction required" — but for server-side targets that interaction is usually an automatic background decode, not a human pressing play. JFrog reported crashes or RCE potential across a wide set of software:
- Self-hosted media servers — Jellyfin (RCE demonstrated via the automatic library scan), Emby, Kodi.
- File / collaboration platforms that auto-generate previews — Nextcloud, Immich, PhotoPrism.
- Desktop thumbnailers —
ffmpegthumbnailerused by GNOME / KDE / XFCE file managers. - NAS appliances — Synology DSM, QNAP — and AI/ML pipelines via PyAV, OpenCV, NVIDIA DALI, Hugging Face Datasets.
- Plex was reported safe — because it builds FFmpeg with an allow-list of only the decoders it needs. That's the reusable lesson, not luck.
The attack chain
From file to impact, with the two outcomes that actually matter — crash versus code execution — and where each is decided:
PixelSmash: from a crafted video to code execution
- Crafted MagicYUV file — A ~50 KB **AVI / MKV / MOV** carrying a MagicYUV stream with an odd `slice_height`. (Not plain MP4.)
- Auto-decoded — An upload or library scan makes Jellyfin / Nextcloud / a thumbnailer **decode it automatically** — `UI:R`, but no human click needed.
- Heap out-of-bounds write — An allocator-vs-decoder rounding mismatch writes **one chroma row past** the heap buffer (CWE-787).
- ASLR off / chained leak? — Reliable RCE was only demonstrated with **ASLR disabled** or by chaining a separate info-leak.
- Crash (DoS) — On a hardened, ASLR-on host the realistic outcome is a **decoder/worker crash** — denial of service.
- RCE as the decoder's user — Overwrite an adjacent `AVBuffer` free pointer → `av_buffer_unref()` makes an **attacker-controlled call** (e.g. `system()`). Mitigation: upgrade to 8.1.2+ and sandbox the transcoder.
Am I exposed?
Exposure here is an inventory problem, not a network scan — there's no endpoint to probe. Check whether the vulnerable decoder is present, then map the libavcodec version that each application actually ships (the OS package update does not fix copies bundled inside apps):
# Is the vulnerable decoder compiled in?
ffmpeg -decoders 2>/dev/null | grep magicyuv # "VFS..D magicyuv" = present
ffmpeg -version # program + libavcodec version (fixed: 8.1.2)
# Read the version out of a bundled / stripped binary (no CLI on PATH):
strings /usr/lib/*/libavcodec.so.* | grep -iE 'Lavc|libavcodec version'
# NOTE: the .so soname major (e.g. .61) is NOT enough — confirm major.minor.micro vs 8.1.2Gate untrusted uploads at the door: run ffprobe and quarantine anything whose codec_name is magicyuv before it reaches a vulnerable decoder. A clean result on one host does not prove your whole estate is safe — bundled copies are the long tail.
Fix it
- Upgrade
libavcodecto FFmpeg 8.1.2+ (or your distro's patched build) everywhere it lives — including the copies bundled inside Jellyfin (jellyfin-ffmpeg), Emby, Electron apps, container images, and NAS firmware. The OS package update misses those. - Can't upgrade yet? Rebuild with
--disable-decoder=magicyuv(MagicYUV is rarely needed), or adopt an allow-list of only the decoders you use — the approach that kept Plex safe. - Sandbox the transcoder — dedicated low-priv user, container,
seccomp/AppArmor, and keep ASLR on. That turns a successful overflow from RCE into a contained crash. - Gate ingest —
ffprobe-and-reject MagicYUV on untrusted uploads, independent of patch state.
FAQ
Is CVE-2026-8461 being exploited in the wild?
Is it remote code execution or just a crash?
How do I fix it?
libavcodec to FFmpeg 8.1.2 or later — and critically, update the FFmpeg bundled inside your apps (Jellyfin, Emby, NAS firmware), not just the OS package. If you can't patch, disable the magicyuv decoder.