3.5 KiB
Mumble 5-MOAD Scan — CLEAN
Target: mumble-voip/mumble (C++ VoIP client + murmur server) Scan date: 2026-03-31 Commit: depth=1 clone of main branch
MOAD-0001 (CWE-407) — CLEAN
Mumble's audio hot path uses correct O(1) data structures throughout:
qhUsers:QHash<unsigned int, ServerUser*>— O(1) session lookupqhPeerUsers:QHash<QPair<HostAddress,quint16>, ServerUser*>— O(1) UDP peer lookupqhHostUsers:QHash<HostAddress, QSet<ServerUser*>>— O(1) host lookup, O(1) membershipm_channelListenerManager: usesQHash<channelID, QSet<session>>— O(1) lookup and membershipWhisperTargetCache:QSet<ServerUser*>for channel and direct targets — O(1) membership- Channel link traversal (
allLinks(),allChildren()): usesQSet::contains— O(1) ACLCache:QHash<User*, QHash<Channel*, Permissions>>— O(1) per-user per-channel cache
Channel::qlUsers is QList<User*> iterated linearly to send audio, but this
is O(U) where U = users in channel — iteration, not membership test. No inner
list search; this is the correct expected cost.
GlobalShortcut::handleButton() calls QList::contains() for qlDownButtons,
qlSuppressed, gs->qlActive — but these represent simultaneously-held
keyboard/mouse buttons (bounded by human finger count, typically <10). Not
filed; not server-driven unbounded growth.
Murmur server voice dispatch path: confirmed clean per-packet.
MOAD-0002 (Intertangle) — OBSERVATION (no ticket)
Global::get() is called 1779 times across the mumble client codebase.
Global holds MainWindow*, AudioInput*, AudioOutput*, ServerHandler*, PluginManager*, Log*, Database*, Settings and dozens of runtime state fields.
This is a classic god-object pattern in a desktop client application.
No ticket filed: this is an architectural observation about a single-user desktop application. There is no shared mutable state between concurrent requests; the Qt event loop serializes GUI access. Refactoring would be a large project and is outside our scope.
MOAD-0003 (Leaked Context) — N/A
Mumble is a single-user desktop client with a thread pool for audio processing.
No thread-local or request-scoped identity carrier pattern. Audio threads do not
carry user-session identity via thread-local storage — they operate on explicit
ServerUser* pointers protected by QReadWriteLock qrwlVoiceThread. N/A.
MOAD-0004 (CWE-312) — CLEAN
No credential logging found in audio or connection paths.
Reviewed:
src/murmur/Messages.cpp: no password in log statementssrc/mumble/ServerHandler.cpp: password fields not passed toqWarning/qDebugsrc/murmur/Meta.cpp: SSL key path logged (not content); failures logged without key material- Token handling (
qslAccessTokens): tokens added/removed without logging their values - Ban list processing: uses
QSet::containsfor deduplication — no log exposure
MOAD-0005 (Thundering Herd) — CLEAN
Murmur server uses QReadWriteLock qrwlVoiceThread for the UDP voice packet
handler. The voice processing thread acquires QReadLocker for normal packet
processing. Write lock is acquired only when inserting a new peer association
(first UDP packet from unknown IP:port pair).
QMutexLocker qmCache protects the ACL cache during whisper target
computation. No unprotected get+null+compute+put pattern found.
qhUsers, qhPeerUsers, qhHostUsers are protected by qrwlVoiceThread.
ACLCache acCache is per-server and protected by qmCache. CLEAN.