| Field | Value |
|---|---|
| Severity | Critical β CVSS 9.3 |
| Product | RingRTC (Signal's calling library), before 2.72.0 β the library behind Signal voice and video calls |
| Type | Improper check for unusual or exceptional conditions (CWE-754) |
| Vector | Remote β a call peer floods the call's FSM event queue so a local hang-up event is never processed; the call's audio (and possibly video) track stays alive after the user hangs up |
- RingRTC before 2.72.0. That covers every Signal client embedding an older RingRTC build β Android, iOS, and Desktop β until the client ships the fixed library.
A local hang-up is not a kill switch: it is just one more event placed at the back of the call's finite-state-machine event queue. The remote peer is trusted with that queue β there is no rate limit on peer-originated events and no priority lane for hang-up. Flood the queue with junk and the hang-up waits behind attacker noise forever, so the call (microphone, possibly camera) is never torn down.
def enqueue(event):
call_fsm.queue.append(event) # no flood guard, no priority
peer.flood(call_fsm.queue) # junk events pile up...
enqueue("hangup") # ...so hang-up sits at the back
call_fsm.drain() # processes junk first β hang-up never runs
def enqueue_fixed(event):
if event == "hangup":
call_fsm.queue.appendleft(event) # critical events jump the queue
elif peer_rate_ok():
call_fsm.queue.append(event) # peer events rate-limited
- The attacker starts a normal Signal call with the victim.
- From their side they saturate the call's FSM event queue with junk events.
- The victim taps hang-up; the event lands at the back of a full queue and is never processed.
- The call's audio track β and possibly the video track β keeps flowing to the attacker while the victim believes the call ended.
The accompanying poc.py demonstrates the pattern safely: a queue model where a flood buries a hang-up event versus a model where hang-up always jumps the queue. Purely synthetic, offline, no network, no real calls β no exploit.
-
Update now : RingRTC 2.72.0 or later fixes the queue handling; on the Signal app, install the latest update from your app store.
-
Verify calls end : after hanging up, double-check the call indicator is gone before discussing anything sensitive.
-
For developers : critical control events must never share a queue with untrusted input β give them a priority lane and rate-limit peer-originated events.
-
RingRTC fix commit: https://github.com/signalapp/ringrtc/commit/4b1b6fa53c9f30c87c8ea78e44675d4a13e1e4d3
-
RingRTC v2.71.0 β v2.72.0: https://github.com/signalapp/ringrtc/compare/v2.71.0...v2.72.0
Educational material only. Do not use against systems you do not own or have explicit permission to test.