# rocketchat-0002: userIds.includes() O(n) per subscription in unread-counter update loop **Target:** RocketChat/Rocket.Chat **Severity:** MEDIUM **CWE:** CWE-407 (Inefficient Algorithmic Complexity) **File:** `apps/meteor/app/lib/server/lib/notifyUsersOnMessage.ts` **Line:** 129 **Status:** PATCHED ## Description `updateUsersSubscriptions()` loads all subscriptions that need updating for a room, then iterates them with `subs.forEach`. Inside that loop (line 128–142) it calls `userIds.includes(sub.u._id)` where `userIds` is a `string[]` built from the union of `mentionIds` and `highlightIds`. For a room with S subscribers and U mentioned/highlighted users the work is O(S × U). This is called on every non-edited, non-threaded message save via the `afterSaveMessage` callback. ```typescript // notifyUsersOnMessage.ts:128-142 subs.forEach((sub) => { const hasUserMention = userIds.includes(sub.u._id); // O(U) per subscriber ... }); ``` ## Fix ```typescript const userIdSet = new Set(userIds); subs.forEach((sub) => { const hasUserMention = userIdSet.has(sub.u._id); // O(1) ... }); ``` ## Complexity | | Before | After | |-|--------|-------| | Per message | O(S × U) | O(S + U) | For a 5 000-member channel with 20 mentioned users: 100 000 → 5 020 comparisons.