All projects with patches now have outreach docs. 276 new docs covering CWE-407, CWE-312, CWE-362 across C, C++, Java, Python, Go, Rust, C#, PHP, Ruby, JavaScript, Dart, Erlang, R, and more. Outreach gap: 276 -> 0.
3.4 KiB
Jami Daemon — CWE-407 Disclosure Brief (jami-daemon)
2026-04-13 · Patch available — awaiting upstream merge
Finding
Two O(n²) defects in Jami daemon's conversation system. Both involve std::find on std::vector for membership testing where std::unordered_set or .count() on an existing set-like container would provide O(1) lookup.
The Defects
jami-daemon-0001 (PATCHED — MEDIUM): src/jamidht/conversation.cpp:783 in loadMessages()
std::vector<std::string> replies;
// For each message:
auto it = std::find(replies.begin(), replies.end(), message.at("reply-to")); // O(R)
if (it == replies.end()) { replies.emplace_back(message.at("reply-to")); }
auto it = std::find(replies.begin(), replies.end(), message.at("id")); // O(R)
if (it != replies.end()) { replies.erase(it); }
replies tracks reply-to references as a std::vector<std::string>. Every message checks membership and inserts/erases with O(R) linear scans, giving O(M*R) total cost where M = messages loaded and R = reply set size.
jami-daemon-0002 (PATCHED — MEDIUM): src/jamidht/conversation_module.cpp (three sites)
std::find(conv->info.members.begin(), conv->info.members.end(), peer)
!= conv->info.members.end()
Three call sites use std::find on conv->info.members (which already supports .count()) to test peer membership. Each fires during conversation sync and contact removal operations.
Complexity Proof
0001: At M=1,000 messages, R=200 replies:
- Defective: 1,000 × 200 × 2 = 400,000 string comparisons
- Fixed: 1,000 × 2 O(1) set operations = 2,000 operations
- ~200× op reduction.
0002: At N=50 conversations, P=100 members each:
- Defective: 50 × 100 = 5,000 comparisons per sync
- Fixed: 50 × O(1) = 50 operations
- ~100× op reduction.
Impact
Jami is a GNU communication platform providing encrypted messaging, video calls, and file sharing. Conversation history loading fires when a user opens or syncs a conversation. Large group conversations with hundreds of messages and reply threads hit the quadratic path in 0001. Conversation sync fires when peers reconnect, hitting 0002 for every conversation.
The Fix
0001: Replace std::vector<std::string> replies with std::unordered_set<std::string>:
std::unordered_set<std::string> replies;
replies.insert(message.at("reply-to")); // O(1)
replies.erase(message.at("id")); // O(1)
0002: Replace std::find(...) != end() with .count() > 0 on the existing container:
// Before: std::find(members.begin(), members.end(), peer) != members.end()
// After: members.count(peer) > 0
Patch
Fix available: defects/jami-daemon/patch/0001.patch and defects/jami-daemon/patch/0002.patch
Two-patch set across conversation.cpp and conversation_module.cpp. 0001: ~200× speedup at 1,000 messages. 0002: ~100× speedup at 100 members.
What We Ask
Patches are ready for review.
- Confirm receipt and assign a GitLab issue reference (savoirfairelinux/jami-daemon).
- Assess severity — 0001 fires on every conversation load; 0002 fires on every peer sync.
- Coordinate a disclosure date — we are targeting 90 days from first contact.
- We will credit the Jami team in the public disclosure. Preferred acknowledgment format welcome.
Contact: see cover email. This brief is confidential until coordinated disclosure.