Audio Before the Call Was Answered — JavaScript Bug Hunt

Modelled on the Apple Group FaceTime bug (January 2019): adding your own number to a group call put the callee's device into a state where it transmitted…

  • Language: JavaScript
  • Layer: Backend
  • Difficulty: Medium
  • Concepts: Security, State Machine
  • Modelled on: Apple FaceTime · 2019
  • Visible tests: a participant added while ringing does not stream; answering starts media for everyone present
  • Reward: 50 XP for a complete fix

Briefing

Modelled on the Apple Group FaceTime bug (January 2019): adding your own number to a group call put the callee's device into a state where it transmitted audio before the call was answered. Apple disabled Group FaceTime server-side for over a week.

call.js starts the media stream as soon as a participant is added, whatever state the call is in.

Fix addParticipant so media only flows once the call is genuinely answered.

Bug report

BUG-FACETIME · Priority: Critical (privacy) · Reported by: security

addParticipant(call, userId) must:

  • add the user to call.participants
  • start streaming that participant's media ONLY when call.state is "answered"
  • while the state is "ringing", the participant is added with streaming false
  • return the resulting participant record

answerCall(call) flips the state to "answered" and starts media for everyone already present.

Observed: adding a participant while the call is still ringing starts their media immediately, so the callee is heard before picking up.

Logs

[call] participant self added while state=ringing streaming=true
[call] callee audio transmitted 11s before answer

The code as shipped

src/calls/call.js (editable)

exports.addParticipant = function (call, userId) {
  var p = { userId: userId, streaming: true };
  call.participants.push(p);
  return p;
};

exports.answerCall = function (call) {
  call.state = "answered";
  for (var i = 0; i < call.participants.length; i++) {
    call.participants[i].streaming = true;
  }
  return call;
};

Read-only context: src/calls/STATES.js.

Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More JavaScript bug hunts.