A critical cryptographic flaw cataloged as CVE-2026-104480 (GHSA-3q99-x36r-rchh) has been patched in libdave, the open-source client reference library powering Discord's Audio & Video End-to-End Encryption (DAVE) protocol. The defect in the library's Messaging Layer Security (MLS, RFC 9420) state machine failed to validate the identity of new group participants during MLS Welcome message ingestion, enabling an adversary in control of the signaling gateway to inject unauthorized rogue participants into private calls and compromise real-time audio and video confidentiality.
The Architecture of Discord's DAVE Protocol
Discord's DAVE protocol was architected to bring scalable end-to-end encryption to massive real-time group voice and video channels. Rather than pairwise Signal Double Ratchet handshakes (which scale quadratically as $O(N^2)$), DAVE relies on the IETF Messaging Layer Security (MLS) tree-based group key exchange, which scales logarithmically ($O(log N)$).
In DAVE, media encryption keys (SRTP / WebRTC) are derived from the MLS epoch root secret. When a client joins an existing voice call, the existing group coordinator generates an MLS Welcome message encrypted to the joiner's KeyPackage. The Welcome message contains the group secrets, current epoch index, and the ratchet tree roster describing all active channel members.
The Roster Validation Breakdown
Under secure MLS operation, a client processing an MLS Welcome message must perform strict verification against an authoritative, out-of-band member identity list (such as Discord's cryptographic channel user directory). Specifically, the client must verify that every leaf node in the ratchet tree corresponds to a recognized, mutual participant in the voice room.
In versions of libdave prior to 1.2.0, this roster verification check was omitted:
// Vulnerable libdave Welcome message processing logic
MLSGroupSession::Status MLSGroupSession::processWelcome(
const mls::Welcome& welcome,
const std::vector<UserId>& expected_roster)
{
auto group = mls::Group::new_from_welcome(welcome, key_store_);
// Group epoch secret derived successfully
current_epoch_ = group.epoch();
// FLAW: Roster comparison was skipped!
// The ratchet tree roster was accepted into active session
// state without asserting that group.roster() matches expected_roster!
active_group_ = std::move(group);
return Status::SUCCESS;
}
Because the check was missing, an adversary in control of the DAVE signaling transport (such as a compromised voice signaling server, an on-path proxy, or a malicious relay node) could manipulate the MLS Welcome message payload. The attacker could insert an additional leaf node containing their own public key into the ratchet tree.
When the joining user connected, their client happily completed the handshake, derived the group epoch media keys, and transmitted audio/video packets encrypted with keys shared directly with the unauthorized eavesdropper.
| Protocol Component | RFC 9420 Requirement | libdave < 1.2.0 Vulnerability |
|---|---|---|
| Ratchet Tree Validation | Validate every leaf credential against out-of-band roster | Omitted; unverified credentials ingested directly |
| Signaling Trust Model | Signaling channel treated as untrusted transport | Assumed signaling gateway would not forge Welcome trees |
| Media Confidentiality | Restricted exclusively to legitimate call attendees | Exposed to injected participant leaf nodes |
Remediation & Protocol Hardening
- Update libdave: Discord client applications and embedded third-party SDKs must upgrade to libdave 1.2.0 or newer immediately. Patched versions strictly compare every leaf node against the server-authenticated participant roster, terminating the session immediately if an unknown identity is present.
- Deploy Epoch Transition Auditing: Communication platforms utilizing MLS must verify that all
CommitandWelcomeproposals enforce cryptographic identity pinning against external Public Key Infrastructure (PKI) or user directories before advancing epoch states.



