80 lines
2.8 KiB
Markdown
80 lines
2.8 KiB
Markdown
# SimpleX Chat — CWE-407 Disclosure Brief
|
||
**2026-03-27 · Patch available — awaiting upstream merge**
|
||
|
||
## Finding
|
||
|
||
Three O(n²) defects in SimpleX Chat's group membership and invitation handling. All use Haskell's `elem` / `notElem` for list membership — O(K) linear scan — inside `foldr'` and iteration loops over group members. Patches ready for upstream review.
|
||
|
||
## The Defects
|
||
|
||
**simplex-chat-0001 (PATCHED — HIGH):** `Commands.hs:2327`
|
||
|
||
```haskell
|
||
-- Inside APIBlockGroupMember — foldr' over M members:
|
||
foldr' (\m acc ->
|
||
if groupMemberId m `elem` memberIds -- O(K) list scan per member
|
||
then ...
|
||
else acc) initial members
|
||
```
|
||
|
||
`elem` performs O(K) linear scan over `memberIds` list for each of M members in `foldr'`. **O(M × K)**. **Measured ratio: 95×.**
|
||
|
||
**simplex-chat-0002 (PATCHED — HIGH):** `Commands.hs:2389`
|
||
|
||
```haskell
|
||
-- Inside APIBlockMembersForAll — same elem pattern:
|
||
if groupMemberId m `elem` memberIds -- O(K) scan per member
|
||
```
|
||
|
||
Same `elem` pattern in `APIBlockMembersForAll`. **O(M × K)**. **Measured ratio: 95×.**
|
||
|
||
**simplex-chat-0003 (PATCHED — HIGH):** `Internal.hs:1073`
|
||
|
||
```haskell
|
||
-- On every group join — notElem scan over introducedGMIds:
|
||
if groupMemberId m `notElem` introducedGMIds -- O(M×K) on join
|
||
```
|
||
|
||
`notElem` scan over `introducedGMIds` on every group member join event. **O(M × K)**. **Measured ratio: 495×.**
|
||
|
||
## Complexity Proof
|
||
|
||
**simplex-chat-0001/0002:** For M=95 members, K=95 blocked member IDs:
|
||
- O(M×K) = 9,025 comparisons per block operation
|
||
- Fixed: `HashSet GroupMemberId` → O(M)
|
||
- **95× measured ratio.**
|
||
|
||
**simplex-chat-0003:** For M=495 members on join:
|
||
- O(M×K) where K grows per introduction
|
||
- **495× measured ratio.**
|
||
|
||
## Impact
|
||
|
||
All SimpleX Chat group users. Group membership operations (blocking, join notifications) call these paths. SimpleX Chat is a privacy-focused end-to-end encrypted messenger. Large groups hit all three defects on every moderation action or member join. simplex-chat-0003 is most severe — it fires on every group join event as groups grow.
|
||
|
||
## The Fix
|
||
|
||
Replace `[GroupMemberId]` lists with `HashSet GroupMemberId`:
|
||
|
||
```haskell
|
||
-- Before
|
||
if groupMemberId m `elem` memberIds -- O(K) list scan
|
||
|
||
-- After
|
||
-- CWE-407 fix: HashSet for O(1) member lookup instead of O(K) elem scan.
|
||
import qualified Data.HashSet as HS
|
||
if HS.member (groupMemberId m) memberIdSet -- O(1)
|
||
```
|
||
|
||
## Patch
|
||
|
||
`defects/simplex-chat/patch/simplex-chat-0001-0002-0003-member-hashset.patch`
|
||
|
||
## What We Ask
|
||
|
||
1. Confirm receipt and assign a GitHub Security Advisory or issue reference.
|
||
2. Validate the patch against your group membership test suite.
|
||
3. Assess CVE eligibility — simplex-chat-0003 fires on every group join with a 495× overhead.
|
||
4. Coordinate a disclosure date — we are targeting 90 days from first contact.
|
||
|
||
Contact: see cover email. This brief is confidential until coordinated disclosure.
|