# UNDF: UNDF-2026-000000162 --- a/server/channels/app/notification.go +++ b/server/channels/app/notification.go @@ -525,6 +525,14 @@ func (a *App) sendNotifications(rctx request.CTX, post *model.Post, team *model. ) + // CWE-407 fix: notificationsForCRT.Push is a model.StringArray ([]string). + // Calling .Contains(id) inside the loops below is O(P) per call where P is + // the length of the Push slice. With N users in mentionedUsersList and M + // users in allActivityPushUserIds the original code is O((N+M)×P). + // Build a map once for O(1) lookups, reducing the total to O(N+M+P). + crtPushSet := make(map[string]bool, len(notificationsForCRT.Push)) + for _, crtID := range notificationsForCRT.Push { + crtPushSet[crtID] = true + } + for _, id := range mentionedUsersList { if profileMap[id] == nil { a.CountNotificationReason(model.NotificationStatusError, model.NotificationTypePush, model.NotificationReasonMissingProfile, model.NotificationNoPlatform) @@ -541,7 +549,7 @@ func (a *App) sendNotifications(rctx request.CTX, post *model.Post, team *model. continue } - if notificationsForCRT.Push.Contains(id) { + if crtPushSet[id] { rctx.Logger().LogM(mlog.MlvlNotificationTrace, "Skipped direct push notification - will send as CRT notification", mlog.String("type", model.NotificationTypePush), mlog.String("post_id", post.Id), @@ -593,7 +601,7 @@ func (a *App) sendNotifications(rctx request.CTX, post *model.Post, team *model. continue } - if notificationsForCRT.Push.Contains(id) { + if crtPushSet[id] { rctx.Logger().LogM(mlog.MlvlNotificationTrace, "Skipped direct push notification - will send as CRT notification", mlog.String("type", model.NotificationTypePush), mlog.String("post_id", post.Id),