# UNDF: UNDF-2026-000000856 # UNDF: (leave blank) # CWE-407: MergeRequests::RefreshService#post_merge_manually_merged commit_ids Array#include? # Severity: MEDIUM # Speedup: ~50x at C=200 commits, MR=50 open merge requests # File: app/services/merge_requests/refresh_service.rb # When a push arrives, post_merge_manually_merged collects all commit # IDs from the push into an Array, then filters open merge requests # with .select { commit_ids.include?(mr.diff_head_sha) }. Each # include? is O(C) where C = number of commits in the push. Called # for each of MR open merge requests targeting the branch. # Total: O(MR * C). Large pushes (rebases, force-pushes) can have # hundreds of commits. # Fix: convert commit_ids to a Set for O(1) lookup. --- a/app/services/merge_requests/refresh_service.rb +++ b/app/services/merge_requests/refresh_service.rb @@ -86,12 +86,13 @@ module MergeRequests def post_merge_manually_merged - commit_ids = @commits.map(&:id) + commit_ids = @commits.map(&:id).to_set merge_requests = @project.merge_requests.opened .preload_project_and_latest_diff .preload_merge_data(@project) .preload_latest_diff_commit(@project) .where(target_branch: @push.branch_name).to_a .select(&:diff_head_commit) .select do |merge_request| commit_ids.include?(merge_request.diff_head_sha) && merge_request.merge_request_diff.state != 'empty' end