Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-86476 — Proof of concept for CVE-2026-86476: GStreamer GstVideoMeta heap out-of-bounds read/write via unixfd deserialization, with ASan repro and RCE chain. | Kitploit
Tools/GitHubGitHub/0xsemizzz/cve-2026-86476
Memory ForensicsVulnerability AnalysisExploitationReverse EngineeringPapers & ResearchBinary Exploitation
GitHub0xsemizzz/cve-2026-86476

CVE-2026-86476

Proof of concept for CVE-2026-86476: GStreamer GstVideoMeta heap out-of-bounds read/write via unixfd deserialization, with ASan repro and RCE chain.

View Repository
1213 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-86476: GstVideoMeta heap buffer overflow

A heap buffer overflow in GStreamer's libgstvideo (gst-plugins-base). A GstVideoMeta describes how a video frame's pixels are laid out in memory. When that description is deserialized from an untrusted unixfd peer, nothing checks that the geometry it claims fits inside the buffer backing it. A peer can set oversized plane strides, and the consumer reads or writes past the allocation.

Details

FieldValue
CVECVE-2026-86476
ClassCWE-125 (out-of-bounds read), CWE-787 (out-of-bounds write), reached through CWE-502 (deserialization of untrusted data)
Componentlibgstvideo: gstvideometa.c, video-frame.c
ImpactOut-of-bounds read (confirmed), out-of-bounds write to code execution (demonstrated)
TriggerA GstVideoMeta with fabricated plane strides, deserialized from a unixfd peer
Fault sitevideo_orc_convert_I420_BGRA, the videoconvert ORC kernel

Root cause

The bug is three missing checks that compound.

  1. No size check in the meta branch of the frame map. gst_video_frame_map_id() in video-frame.c has two branches. The no-meta branch ends with if (frame->map[0].size < info->size) goto invalid_size;. The meta branch, taken whenever a GstVideoMeta is present, only enforces info->width <= meta->width and info->height <= meta->height. Those are lower bounds. Nothing compares the plane geometry against the size of the real memory.

  2. default_map() checks one byte per plane. In gstvideometa.c, the plane memory is resolved with gst_buffer_find_memory(buffer, offset, 1, ...). The size argument is 1. The code confirms a single byte exists at the plane's start offset, then copies the stride out as is. The real extent of the plane, stride * height, is never compared against the allocation. A FIXME use plane size comment sits directly above the check.

  3. The deserializer range-checks nothing. video_meta_deserialize() validates only that the byte reader did not run out of input, that n_planes <= GST_VIDEO_MAX_PLANES, and that version != 0. Offsets and strides are copied straight out of the stream. Each stride is read as a signed gint32, so a negative stride is accepted.

On the receiving side, gst_unix_fd_src_create() deserializes the metas against an empty buffer and attaches the peer's memory afterward. The stride the meta carries and the size of the memory that backs the buffer are never compared.

Impact path

A hostile peer serializes a GstVideoMeta for a 320x240 I420 frame with every plane stride set to 1000000. The consumer deserializes it without a range check, attaches the small real memory, and maps the frame. default_map() is satisfied because the first byte of each plane exists. videoconvert then reads each input plane for stride * height bytes and walks past the allocation.

That is the read. The write is the mirror image. gst_video_frame_copy_plane() does a memcpy of stride * height bytes, so when a small buffer carrying the lying meta is the destination of a copy, the memcpy writes past its backing.

The unixfd transport copies non-FD buffers into a memfd, so the stock pipeline lands the read against an mmap'd mapping boundary (crash and information leak). Driving the same deserializer with the same untrusted bytes against a heap-backed destination exercises the write primitive. The transport decides whether the overflow hits a mapping boundary or the heap. It does not decide whether the bug exists.

With the heap write, the proof of concept overwrites the free function pointer in the header of a neighbouring GstMiniObject, places the command string where it lands in the first argument register, and triggers an unref so the forged pointer is called as system().

Affected configurations

Any pipeline that accepts video buffers over unixfd from a process it does not fully trust. Sandboxed media decoders, portal-style split pipelines, and anything using unixfdsrc to receive frames across a privilege or trust boundary.

Confirmed:

  • Read side against a GStreamer build with AddressSanitizer.
  • Write side against Debian's libgstreamer-1.0.so.0.2804.0 (1.28.4-2) with glibc 2.42.

Reproduction

Two processes over a unix socket, stock elements only.

  • Sender: fakesrc ! capsfilter ! unixfdsink, pushing a valid 320x240 I420 buffer with real strides 320/160/160 but a GstVideoMeta whose plane strides are 1000000.
  • Receiver: unixfdsrc ! videoconvert ! capsfilter ! fakesink, where the capsfilter forces I420 to BGRA so videoconvert must read the frame by the meta strides.
RunMeta stridesResult
11000000 / 1000000 / 1000000out-of-bounds read under ASan in video_orc_convert_I420_BGRA
2320 / 160 / 160normal completion, buffer reaches fakesink

Build GStreamer with -Db_sanitize=address for the read-side proof. The RCE proof of concept runs on a stock build, because an ASan build aborts on the first overflowing memcpy.

Fix direction

  • In default_map(), replace the one-byte gst_buffer_find_memory(..., 1, ...) with a check against the stride * height plane extent.
  • Give the meta branch of gst_video_frame_map_id() the same invalid_size check the no-meta branch has.
  • In video_meta_deserialize(), range-check offsets and strides against the buffer, and reject negative strides.

Any one of these breaks the chain. All three is the correct fix for a structure that crosses a trust boundary.

References

  • CVE record: https://www.cve.org/CVERecord?id=CVE-2026-86476
  • Proof of concept: https://github.com/0xSemizzz/CVE-2026-86476
Download Tool