/ws Unauthenticated Call-Control Abuse via Attacker-Supplied Call SIDThe pipecat development runner registers a /ws WebSocket endpoint for telephony testing that accepts connections without any authentication. An unauthenticated remote attacker who can reach an exposed runner endpoint can connect to this endpoint, send a crafted Twilio handshake message containing an attacker-supplied callSid, and cause the server to issue an authenticated Twilio REST API hang-up request against that call SID using the server operator's own credentials. This may allow the attacker to forcibly terminate an active call on the victim's Twilio account if the attacker knows or obtains a valid call SID for that account. Equivalent unauthenticated call-control sinks exist for Telnyx and Plivo. Maintainers are evaluating the final CVSS 3.1 score.
The pipecat development runner registers a WebSocket route at /ws (src/pipecat/runner/run.py:1116). When a client connects, the server immediately accepts the connection without performing any authentication or signature verification (run.py:1119):
await websocket.accept() # run.py:1119 — no auth check before this point
After acceptance, the server reads the Twilio WebSocket stream-start handshake and extracts the callSid field verbatim from the attacker-controlled JSON payload (src/pipecat/runner/utils.py:223):
call_id: start_data.get("callSid") # utils.py:223 — tainted, attacker-supplied
The tainted call_id is then passed directly into TwilioFrameSerializer alongside the server's own Twilio account credentials, which are read from environment variables (src/pipecat/runner/utils.py:513-517):
TwilioFrameSerializer(
stream_sid=stream_id,
call_sid=call_id, # TAINTED
account_sid=os.getenv("TWILIO_ACCOUNT_SID"), # server credential...
0.0.1000.0.1010.0.1020.0.1030.0.1040.0.1050.0.1060.0.1070.0.1080.0.77+27 more1.4.0Exploitability
AV:NAC:HPR:NUI:NScope
S:CImpact
C:NI:LA:HCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:H