VYPR
High severity8.7GHSA Advisory· Published May 14, 2026· Updated May 15, 2026

CVE-2026-44700

CVE-2026-44700

Description

Elixir WebRTC is an Elixir implementation of the W3C WebRTC API. Prior to 0.15.1 and 0.16.1, missing DTLS peer certificate fingerprint validation in the DTLS client (active) role removes one side of WebRTC's mutual authentication. The bug is not independently exploitable for media interception in standard deployments, but enables a full man-in-the-middle attack when chained with insecure signalling or a peer with similar validation gaps. This vulnerability is fixed in 0.15.1 and 0.16.1.

Affected products

1

Patches

1
658c63221a86

[FCE-3227] Fix DTLS fingerprint not being validated in certain cases (#250)

https://github.com/elixir-webrtc/ex_webrtcJakub PisarekMay 4, 2026via ghsa
2 files changed · +65 31
  • lib/ex_webrtc/dtls_transport.ex+29 26 modified
    @@ -481,34 +481,10 @@ defmodule ExWebRTC.DTLSTransport do
             {:ok, state}
     
           {:handshake_finished, lkm, rkm, profile, packets} ->
    -        Logger.debug("DTLS handshake finished")
    -        state = update_remote_cert_info(state)
    -        :ok = do_send(state, packets)
    -
    -        peer_fingerprint =
    -          state.dtls
    -          |> ExDTLS.get_peer_cert()
    -          |> ExDTLS.get_cert_fingerprint()
    -          |> Utils.hex_dump()
    -
    -        if peer_fingerprint == state.peer_fingerprint do
    -          :ok = setup_srtp(state, lkm, rkm, profile)
    -          state = update_dtls_state(state, :connected)
    -          state = flush_buffered_remote_rtp_packets(state)
    -          {:ok, state}
    -        else
    -          Logger.debug("Non-matching peer cert fingerprint.")
    -          state = update_dtls_state(state, :failed)
    -          {:ok, state}
    -        end
    +        handle_handshake_finished(state, lkm, rkm, profile, packets)
     
           {:handshake_finished, lkm, rkm, profile} ->
    -        Logger.debug("DTLS handshake finished")
    -        :ok = setup_srtp(state, lkm, rkm, profile)
    -        state = update_dtls_state(state, :connected)
    -        state = flush_buffered_remote_rtp_packets(state)
    -        state = update_remote_cert_info(state)
    -        {:ok, state}
    +        handle_handshake_finished(state, lkm, rkm, profile)
     
           :handshake_want_read ->
             {:ok, state}
    @@ -554,6 +530,33 @@ defmodule ExWebRTC.DTLSTransport do
         {:ok, state}
       end
     
    +  defp handle_handshake_finished(state, lkm, rkm, profile, packets \\ []) do
    +    Logger.debug("DTLS handshake finished")
    +
    +    if peer_fingerprint_matching?(state) do
    +      :ok = setup_srtp(state, lkm, rkm, profile)
    +      state = update_dtls_state(state, :connected)
    +      state = flush_buffered_remote_rtp_packets(state)
    +      state = update_remote_cert_info(state)
    +      :ok = do_send(state, packets)
    +      {:ok, state}
    +    else
    +      Logger.debug("Non-matching peer cert fingerprint.")
    +      state = update_dtls_state(state, :failed)
    +      {:ok, state}
    +    end
    +  end
    +
    +  defp peer_fingerprint_matching?(%{peer_fingerprint: expected_fp} = state) do
    +    actual_fp =
    +      state.dtls
    +      |> ExDTLS.get_peer_cert()
    +      |> ExDTLS.get_cert_fingerprint()
    +      |> Utils.hex_dump()
    +
    +    expected_fp == actual_fp
    +  end
    +
       defp setup_srtp(state, local_keying_material, remote_keying_material, profile) do
         {:ok, crypto_profile} =
           ExLibSRTP.Policy.crypto_profile_from_dtls_srtp_protection_profile(profile)
    
  • test/ex_webrtc/dtls_transport_test.exs+36 5 modified
    @@ -163,8 +163,15 @@ defmodule ExWebRTC.DTLSTransportTest do
         ice_transport: ice_transport,
         ice_pid: ice_pid
       } do
    -    :ok = DTLSTransport.start_dtls(dtls, :active, @fingerprint)
         remote_dtls = ExDTLS.init(mode: :server, dtls_srtp: true)
    +
    +    remote_fingerprint =
    +      remote_dtls
    +      |> ExDTLS.get_cert()
    +      |> ExDTLS.get_cert_fingerprint()
    +      |> Utils.hex_dump()
    +
    +    :ok = DTLSTransport.start_dtls(dtls, :active, remote_fingerprint)
         :ok = DTLSTransport.set_ice_connected(dtls)
     
         # perform DTLS-SRTP handshake
    @@ -240,9 +247,15 @@ defmodule ExWebRTC.DTLSTransportTest do
         ice_transport: ice_transport,
         ice_pid: ice_pid
       } do
    -    :ok = DTLSTransport.start_dtls(dtls, :active, @fingerprint)
         remote_dtls = ExDTLS.init(mode: :server, dtls_srtp: true)
     
    +    remote_fingerprint =
    +      remote_dtls
    +      |> ExDTLS.get_cert()
    +      |> ExDTLS.get_cert_fingerprint()
    +      |> Utils.hex_dump()
    +
    +    :ok = DTLSTransport.start_dtls(dtls, :active, remote_fingerprint)
         :ok = DTLSTransport.set_ice_connected(dtls)
     
         assert {:ok, _, _, _} = check_handshake(dtls, ice_transport, ice_pid, remote_dtls)
    @@ -296,9 +309,15 @@ defmodule ExWebRTC.DTLSTransportTest do
         ice_transport: ice_transport,
         ice_pid: ice_pid
       } do
    -    :ok = DTLSTransport.start_dtls(dtls, :active, @fingerprint)
         remote_dtls = ExDTLS.init(mode: :server, dtls_srtp: true)
     
    +    remote_fingerprint =
    +      remote_dtls
    +      |> ExDTLS.get_cert()
    +      |> ExDTLS.get_cert_fingerprint()
    +      |> Utils.hex_dump()
    +
    +    :ok = DTLSTransport.start_dtls(dtls, :active, remote_fingerprint)
         :ok = DTLSTransport.set_ice_connected(dtls)
     
         assert {:ok, _, _, _} = check_handshake(dtls, ice_transport, ice_pid, remote_dtls)
    @@ -328,9 +347,15 @@ defmodule ExWebRTC.DTLSTransportTest do
         ice_transport: ice_transport,
         ice_pid: ice_pid
       } do
    -    :ok = DTLSTransport.start_dtls(dtls, :active, @fingerprint)
         remote_dtls = ExDTLS.init(mode: :server, dtls_srtp: true)
     
    +    remote_fingerprint =
    +      remote_dtls
    +      |> ExDTLS.get_cert()
    +      |> ExDTLS.get_cert_fingerprint()
    +      |> Utils.hex_dump()
    +
    +    :ok = DTLSTransport.start_dtls(dtls, :active, remote_fingerprint)
         :ok = DTLSTransport.set_ice_connected(dtls)
     
         # perform DTLS-SRTP handshake
    @@ -380,9 +405,15 @@ defmodule ExWebRTC.DTLSTransportTest do
         ice_transport: ice_transport,
         ice_pid: ice_pid
       } do
    -    :ok = DTLSTransport.start_dtls(dtls, :active, @fingerprint)
         remote_dtls = ExDTLS.init(mode: :server, dtls_srtp: true)
     
    +    remote_fingerprint =
    +      remote_dtls
    +      |> ExDTLS.get_cert()
    +      |> ExDTLS.get_cert_fingerprint()
    +      |> Utils.hex_dump()
    +
    +    :ok = DTLSTransport.start_dtls(dtls, :active, remote_fingerprint)
         :ok = DTLSTransport.set_ice_connected(dtls)
     
         # perform DTLS-SRTP handshake
    

Vulnerability mechanics

AI mechanics synthesis has not run for this CVE yet.

References

8

News mentions

0

No linked articles in our index yet.