Problem
crates/client/src/listeners.rs:329-343 processes VoiceJoin messages without verifying that the claimed peer_id matches the cryptographic signer of the wire message:
crate::ops::WireMessage::VoiceJoin {
channel_id,
peer_id, // ← self-declared, never verified against `signer`
} => {
let ch = channel_id.clone();
willow_actor::state::mutate(&ctx.voice, move |v| {
v.participants.entry(ch).or_default().insert(peer_id);
})
.await;
}
The signer variable (verified by unpack_wire) is available in scope but never compared to peer_id. The same issue affects VoiceLeave (line 345) and partially VoiceSignal (line 363 — signal uses signer for from_peer but the target check doesn't validate the source).
Attack Scenario
- Malicious peer signs a
VoiceJoin message with their own key
- Sets
peer_id to the victim's endpoint ID
- All peers' UIs show the victim as having joined the voice channel
- Can also forge
VoiceLeave to make it appear someone left
Severity
HIGH — allows impersonation in voice channels and social engineering attacks.
Fix
Add signer verification before processing voice messages:
crate::ops::WireMessage::VoiceJoin { channel_id, peer_id } => {
if peer_id != signer {
return; // Reject spoofed voice join
}
// ... existing logic
}
Apply the same check to VoiceLeave.
Locations
crates/client/src/listeners.rs:329-343 — VoiceJoin
crates/client/src/listeners.rs:345-361 — VoiceLeave
Problem
crates/client/src/listeners.rs:329-343processesVoiceJoinmessages without verifying that the claimedpeer_idmatches the cryptographic signer of the wire message:The
signervariable (verified byunpack_wire) is available in scope but never compared topeer_id. The same issue affectsVoiceLeave(line 345) and partiallyVoiceSignal(line 363 — signal usessignerforfrom_peerbut the target check doesn't validate the source).Attack Scenario
VoiceJoinmessage with their own keypeer_idto the victim's endpoint IDVoiceLeaveto make it appear someone leftSeverity
HIGH — allows impersonation in voice channels and social engineering attacks.
Fix
Add signer verification before processing voice messages:
Apply the same check to
VoiceLeave.Locations
crates/client/src/listeners.rs:329-343— VoiceJoincrates/client/src/listeners.rs:345-361— VoiceLeave