java-topology/defects/grafana/patch/grafana-0001-dashboard-shared-user-dedup.patch
russell@unturf.com 689ec25d05 grafana: 3 CWE-407 defects; loki: 1 CWE-407 defect; 4/4 PASS
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
2026-03-30 13:17:58 -04:00

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)
}
}