java-topology/defects/mumble-scan/CLEAN.md

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 lookup
  • qhPeerUsers: QHash<QPair<HostAddress,quint16>, ServerUser*> — O(1) UDP peer lookup
  • qhHostUsers: QHash<HostAddress, QSet<ServerUser*>> — O(1) host lookup, O(1) membership
  • m_channelListenerManager: uses QHash<channelID, QSet<session>> — O(1) lookup and membership
  • WhisperTargetCache: QSet<ServerUser*> for channel and direct targets — O(1) membership
  • Channel link traversal (allLinks(), allChildren()): uses QSet::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 statements
  • src/mumble/ServerHandler.cpp: password fields not passed to qWarning/qDebug
  • src/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::contains for 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.