SIPSORCERY · CVE-2026-123805 · Package
FIX → 10.0.14
A peer that has completed a WebRTC handshake can send one malformed SCTP SACK chunk that makes SIPSorcery read past its receive buffer. The receive thread then exits, which permanently drops the SCTP association and every data channel on it.
first public Aug 10, 2026 · 2 sources
Could this affect your app?
Free first check from your website. Connect your repo for the full answer.
Applications that use SIPSorcery's WebRTC data channel (SCTP) transport and accept connections from untrusted peers. Projects that only use SIPSorcery for SIP signalling or media without data channels are unlikely to be exposed, though the sources do not say this explicitly.
Not affected if no-data-channels, version-10.0.14-or-later
Who cares dotnet, sctp, sipsorcery, webrtc
dotnet list package; versions 10.0.13 and earlier are affected.Upgrade to 10.0.14
10.0.14.SctpSackChunk.ParseChunk reads the numGapAckBlocks and numDuplicateTSNs fields (each up to 65535) directly from an attacker-controlled SCTP SACK chunk and loops that many times reading 4 bytes per iteration, with no validation of the counts against the chunk length or the receive buffer. A single crafted SACK chunk from a negotiated WebRTC peer forces reads past the end of the 262144-byte receive buffer, raising IndexOutOfRangeException, which is not caught by the recoverable handler and terminates the dedicated SCTP receive thread — permanently killing the SCTP association and all data channels.
src/SIPSorcery/net/SCTP/Chunks/SctpSackChunk.cs:
ushort numGapAckBlocks = NetConvert.ParseUInt16(buffer, startPosn + 8); (:141)ushort numDuplicateTSNs = NetConvert.ParseUInt16(buffer, startPosn + 10); (:142)NetConvert.ParseUInt16/32 (buffer[posn], no bounds check — ).
(SctpPacket.cs:195-203) only validates and ; the counts inside the value are never checked. calls on a reused .Check it with your coding agent
It reads this page and tells you if your code is affected.
Are you affected?
Ask from here. InfraStack checks the affected versions against your stack and answers in your inbox.
InfraStack checks the affected versions against your stack and answers in Slack, with the evidence and the fix.
sys/Net/NetConvert.cs:30,41SctpPacket.ParseChunkschunkLength >= 4posn+chunkLength <= lengthRTCSctpTransport.DoReceiveSctpPacket.Parse(recvBuffer, 0, bytesRead)recvBuffer = new byte[262144]IndexOutOfRangeException is a SystemException, not ApplicationException, so the recoverable catch (ApplicationException) { … continue; } at RTCSctpTransport.cs:345 is skipped and control falls to the generic catch (Exception) { … break; } at :356. The break exits the receive loop, DoReceive returns, and the dedicated _receiveThread = new Thread(DoReceive) (:173, started once) exits with no restart → the SCTP association and every data channel are permanently dead (denial of service).
A negotiated WebRTC peer (post-DTLS) sends a checksum-valid SCTP packet: 12-byte common header + a SACK chunk (type 3) with chunkLength=16, numGapAckBlocks=0xFFFF, numDuplicateTSNs=0xFFFF. CRC32C is attacker-computable. The gap-ack loop reaches buffer[262144] on a 262144-byte array (valid indices 0..262143) → IndexOutOfRangeException.
chunkLength=16, numGapAckBlocks=0xFFFF). Guard: VerifyChecksum (CRC32C). Bypass: CRC32C is computable by the sender.DoReceive (RTCSctpTransport.cs:286) reads into reused recvBuffer (262144 bytes, :280) → SctpPacket.Parse(recvBuffer, 0, bytesRead) (:302) → ParseChunks → SACK dispatch (SctpChunk.Parse :340-341) → SctpSackChunk.ParseChunk. Guard: ParseChunks checks only chunkLength>=4 and posn+chunkLength<=length (SctpPacket.cs:195-203). Bypass: chunkLength=16 is well-formed; the counts are never validated.NetConvert.ParseUInt16(buffer, reportPosn) with reportPosn starting at startPosn(16)+FIXED_PARAMETERS(12)=28, climbing +4 each iteration. Guard: none on the count. Bypass: NetConvert.ParseUInt16 (NetConvert.cs:30) indexes buffer[posn] unchecked.reportPosn = 28 + 65529*4 = 262144 → buffer[262144] → IndexOutOfRangeException → generic catch at RTCSctpTransport.cs:356 → break → receive thread exits, no restart → association permanently dead.NetConvert.ParseUInt16 unchecked indexing (NetConvert.cs:30).ParseChunks validates only chunkLength (SctpPacket.cs:195-203).28 + 65535*4 = 262168 > 262144; buffer is 262144 (DEFAULT_ADVERTISED_RECEIVE_WINDOW, SctpAssociation.cs:62). numGapAckBlocks alone suffices — the dup-TSN loop is not needed.DoReceive catch split: recoverable catch(ApplicationException) at :345 (continue) vs generic catch(Exception) at :356 (break); _receiveThread started once at :176.nuget:SIPSorcery <= 10.0.13 (verified present on release tag v10.0.13 and HEAD da944543).
NOT a duplicate of GHSA-qmvg-569h-hqrh — that fix (fe5a1fa) touched only SctpPacket.cs (the chunk-cursor zero-length infinite loop, CWE-835). This is a distinct out-of-bounds read (CWE-125) in SctpSackChunk count loops, untouched by that fix.
Validate startPosn + FIXED_PARAMETERS_LENGTH + numGapAckBlocks*4 + numDuplicateTSNs*4 <= posn + chunkLen before the loops, and/or make NetConvert.Parse* bounds-checked, and/or treat IndexOutOfRangeException/ArgumentException as recoverable in DoReceive.
Reported by zx (Jace) — GitHub: @manus-use
This page as .md · .json · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
GitHub Advisory Database, CC-BY 4.0 · NVD data is provided by NIST and is public domain. Posts quoted belong to their authors.