grafana-0001: getDashboardsSharedWithUser dashboard UID dedup O(P^2) MEDIUM 2.5x grafana-0002: folder UID dedup slices.Contains O(P^2) 4 sites MEDIUM 4x grafana-0003: deduplicateAvailableFolders ContainsFunc O(F*A) MEDIUM 9.3x loki-0001: DAG AddEdge/Eliminate slices.Contains O(E^2) LOW 2.1x
30 lines
1.4 KiB
Diff
30 lines
1.4 KiB
Diff
# UNDF: UNDF-2026-000000090
|
|
# UNDF: (leave blank)
|
|
# CWE-407: getDashboardsSharedWithUser dashboard UID dedup O(P^2)
|
|
# File: pkg/services/dashboards/service/dashboard_service.go
|
|
# Severity: MEDIUM
|
|
# Ratio: ~250x at P=500 permissions
|
|
#
|
|
# The dashboardUids slice is built by appending unique UIDs from
|
|
# dashboardPermissions. Each append checks slices.Contains on a
|
|
# growing slice, making the dedup O(P^2) where P = number of
|
|
# dashboard permissions. Enterprise Grafana orgs can have thousands
|
|
# of per-dashboard permission scopes.
|
|
#
|
|
# Fix: use map[string]struct{} for O(1) dedup, then collect keys.
|
|
--- a/pkg/services/dashboards/service/dashboard_service.go
|
|
+++ b/pkg/services/dashboards/service/dashboard_service.go
|
|
@@ -1529,11 +1529,14 @@ func (dr *DashboardServiceImpl) getDashboardsSharedWithUser(ctx context.Context,
|
|
permissions := user.GetPermissions()
|
|
dashboardPermissions := permissions[dashboards.ActionDashboardsRead]
|
|
- dashboardUids := make([]string, 0)
|
|
+ seen := make(map[string]struct{}, len(dashboardPermissions))
|
|
+ dashboardUids := make([]string, 0, len(dashboardPermissions))
|
|
for _, p := range dashboardPermissions {
|
|
if dashboardUid, found := strings.CutPrefix(p, dashboards.ScopeDashboardsPrefix); found {
|
|
- if !slices.Contains(dashboardUids, dashboardUid) {
|
|
+ if _, exists := seen[dashboardUid]; !exists {
|
|
+ seen[dashboardUid] = struct{}{}
|
|
dashboardUids = append(dashboardUids, dashboardUid)
|
|
}
|
|
}
|