From f34b77985e9b282a2e930cc1f91e2d23b7ccef46 Mon Sep 17 00:00:00 2001 From: Jo Turk Date: Wed, 21 Oct 2026 02:39:31 +0300 Subject: [PATCH] Zero RTP padding when marshaling into reused buffers Initialize padding bytes in the shared marshalling helper so Packet.MarshalTo and MarshalPacketTo cannot expose stale buffer contents. Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-YQVAINZJ. https://github.com/pion/webrtc/issues/3642 --- packet.go | 3 +++ packet_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/packet.go b/packet.go index 6d2c7f3..8160fea 100644 --- a/packet.go +++ b/packet.go @@ -556,6 +556,9 @@ func marshalPayloadAndPaddingTo(buf []byte, offset int, header *Header, payload } m := copy(buf[offset:], payload) + // Padding is part of the serialized packet and must not expose stale data + // when the caller reuses a buffer. + clear(buf[offset+m : offset+m+int(paddingSize)]) if header.Padding { buf[offset+m+int(paddingSize-1)] = paddingSize diff --git a/packet_test.go b/packet_test.go index a607449..62a9434 100644 --- a/packet_test.go +++ b/packet_test.go @@ -4,10 +4,12 @@ package rtp import ( + "bytes" "fmt" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestBasic(t *testing.T) { // nolint:maintidx,cyclop @@ -1708,3 +1710,36 @@ func BenchmarkUnmarshalHeader(b *testing.B) { } }) } + +func TestMarshalToInitializesPadding(t *testing.T) { + for _, paddingSize := range []byte{0, 1, 4, 255} { + for _, api := range []string{"Packet", "MarshalPacketTo", "DeprecatedPaddingSize"} { + t.Run(fmt.Sprintf("%s/padding=%d", api, paddingSize), func(t *testing.T) { + packet := Packet{ + Header: Header{Version: 2, Padding: paddingSize > 0, PaddingSize: paddingSize}, + Payload: []byte{1, 2, 3}, + } + if api == "DeprecatedPaddingSize" { + packet.Header.PaddingSize = 0 + packet.PaddingSize = paddingSize + } + + // A fresh allocation provides the expected wire encoding. + // reusing buffer exposed media data for FlexFEC users. + expected, err := packet.Marshal() + require.NoError(t, err) + buf := bytes.Repeat([]byte{0xa5}, len(expected)+16) + var n int + if api == "MarshalPacketTo" { + n, err = MarshalPacketTo(buf, &packet.Header, packet.Payload) + } else { + n, err = packet.MarshalTo(buf) + } + require.NoError(t, err) + require.Equal(t, len(expected), n) + assert.Equal(t, expected, buf[:n]) + assert.Equal(t, bytes.Repeat([]byte{0xa5}, 16), buf[n:], "bytes beyond the packet must be untouched") + }) + } + } +}