REDHAT-BUG-2563952: High severity GStreamer gst-plugins-good vulnerability
GStreamer gst-plugins-good ships the rtph264depay element (gst/rtp/gstrtph264depay.c). MTAP16 (NAL type 26) and MTAP24 (NAL type 27) support was added in gst-plugins-good 1.28.0 (upstream commit 367cda03c9, 2025-10-08).
In gstrtph264depayprocess() the variable payloadlen is declared as gint (signed 32-bit). For the MTAP16/MTAP24 branch (lines 1380-1471), the code strips the 1-byte NAL type header (line 1387) and then unconditionally strips the 2-byte decoding-order-number base (DON base, line 1396) without first checking that at least 2 bytes remain. When the RTP payload is truncated (e.g., only 1 byte — just the NAL type), payloadlen goes negative (e.g., 1-1-2 = -2).
Bug 1 — Wrong loop guard (line 1398): aggregationunitsize is gsize (unsigned). The comparison 'while (payloadlen > aggregationunitsize)' performs an unsigned promotion of the signed payloadlen. A negative payloadlen (e.g., -2) becomes a very large unsigned value (0xFFFFFFFE on 32-bit), so the loop condition is TRUE and the loop body executes even though the packet is exhausted.
Bug 2 — Broken clamping (line 1427): Inside the loop, nalusize is read via GSTREADUINT16BE() from the payload pointer that is already past the end of the packet buffer (OOB heap read #1). The subsequent clamping guard 'if (nalusize > payloadlen)' is also a signed/unsigned comparison: nalusize is guint, payloadlen is gint (still negative). Negative payloadlen is promoted to a huge unsigned value, so the condition evaluates FALSE and nalusize is NOT clamped. nalusize may be up to 65535.
Bug 3 — memcpy from OOB (line 1441): memcpy(map.data + sizeof(syncbytes), payload, nalusize) reads nalusize (up to 65535) bytes from payload, which points past the end of the actual packet. This is the primary heap-buffer-over-read confirmed by ASan: READ of 48830 bytes at gstrtph264depay.c:1432.
The allocated output buffer (outbuf) has exactly nalusize+4 bytes; the DESTINATION is valid. Only the SOURCE is OOB. The content is then placed into the depayloaded output GstBuffer and forwarded downstream. In relay/transcode pipelines this becomes observable information disclosure. In all pipelines, the OOB read is likely to crash the process (SIGSEGV) when the read range extends into unmapped memory.
Affected: gst-plugins-good 1.28.0 through 1.28.8. Fixed in: 1.28.9 (unreleased as of 2026-10-28, private MR gstreamer-security !136). GStreamer advisory SA-2026-0095.
Reporter: Claude (Anthropic), Ada Logics. PSIRT ticket: PSIRTSUPT-29444.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
gst-plugins-goodto a version that resolves this vulnerability.Fixed in 1.28.9
Event History
Frequently Asked Questions
What traffic is needed to trigger the vulnerable code path?
An attacker needs to provide a truncated RTP payload using an H.264 MTAP16 (NAL type 26) or MTAP24 (NAL type 27) packet. A payload containing only the one-byte NAL type is sufficient to make the remaining payload length negative.
Which deployments are most likely exposed?
Deployments that use the GStreamer gst-plugins-good rtph264depay element to process RTP H.264 streams containing MTAP16 or MTAP24 packets are relevant. MTAP16 and MTAP24 support was added in gst-plugins-good 1.28.0.
How can I determine whether a suspicious packet reached the flawed handling path?
Inspect RTP H.264 input for MTAP16 or MTAP24 NAL types with truncated payloads, particularly packets that contain the NAL-type byte but do not contain the required two-byte decoding-order-number base. In that case, the code subtracts the header and DON-base lengths and can enter the aggregation loop with a negative signed payload length.