Skip to content

Commit 6c43e68

Browse files
committed
endpoint card
1 parent ca5d22a commit 6c43e68

File tree

2 files changed

+29
-49
lines changed

2 files changed

+29
-49
lines changed

graphql/modules/endpoints/resolvers.go

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,6 @@ func ResolveEndpointDetails(db database.DBConnection, endpointName string) (map[
394394
}
395395

396396
// ResolveSyncedEndpoints fetches a list of endpoints that have been synced.
397-
// REFACTORED: Now uses release2cve materialized edges instead of complex AQL filtering
398397
func ResolveSyncedEndpoints(db database.DBConnection, limit int, org string) ([]map[string]interface{}, error) {
399398
ctx := context.Background()
400399

@@ -605,10 +604,19 @@ func ResolveSyncedEndpoints(db database.DBConnection, limit int, org string) ([]
605604
continue
606605
}
607606

608-
// NO VALIDATION NEEDED - edges are pre-validated during ingestion
607+
// LOGIC MATCH: Deduplicate per RELEASE (just like ResolveEndpointDetails)
609608
var validVulns []map[string]interface{}
609+
seen := make(map[string]bool)
610610

611611
for _, v := range res.Vulns {
612+
// Local deduplication for this release (CVE + Package)
613+
// This handles duplicate edges in the DB for the same release
614+
key := v.CveID + ":" + v.Package
615+
if seen[key] {
616+
continue
617+
}
618+
seen[key] = true
619+
612620
validVulns = append(validVulns, map[string]interface{}{
613621
"cve_id": v.CveID,
614622
"severity_rating": v.SeverityRating,
@@ -634,30 +642,14 @@ func ResolveSyncedEndpoints(db database.DBConnection, limit int, org string) ([]
634642
prevCounts := map[string]int{"critical": 0, "high": 0, "medium": 0, "low": 0}
635643

636644
for _, svc := range ep.Services {
637-
// FIX: Move deduplication maps INSIDE the service loop to deduplicate per service (matches Details view)
638-
seen := make(map[string]bool)
639-
seenPrev := make(map[string]bool)
645+
// LOGIC MATCH: Sum across all services WITHOUT further deduplication
646+
// This counts instances (e.g. Vuln X in Service A and Service B counts as 2)
640647

641648
// 1. Current Vulnerabilities
642649
currKey := svc.Name + ":" + svc.Current.Version
643650
currVulns := releaseVulnMap[currKey]
644651

645652
for _, v := range currVulns {
646-
cveID := v["cve_id"].(string)
647-
648-
// Ensure we handle package info for deduplication
649-
pkg := ""
650-
if p, ok := v["package"].(string); ok {
651-
pkg = p
652-
}
653-
// Use composite key to count Instances (matching Details view)
654-
dedupKey := cveID + ":" + pkg
655-
656-
if seen[dedupKey] {
657-
continue
658-
}
659-
seen[dedupKey] = true
660-
661653
rating := v["severity_rating"].(string)
662654
switch rating {
663655
case "CRITICAL":
@@ -677,19 +669,6 @@ func ResolveSyncedEndpoints(db database.DBConnection, limit int, org string) ([]
677669
prevVulns := releaseVulnMap[prevKey]
678670

679671
for _, v := range prevVulns {
680-
cveID := v["cve_id"].(string)
681-
682-
pkg := ""
683-
if p, ok := v["package"].(string); ok {
684-
pkg = p
685-
}
686-
dedupKey := cveID + ":" + pkg
687-
688-
if seenPrev[dedupKey] {
689-
continue
690-
}
691-
seenPrev[dedupKey] = true
692-
693672
rating := v["severity_rating"].(string)
694673
switch rating {
695674
case "CRITICAL":

graphql/modules/releases/resolvers.go

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ package releases
44
import (
55
"context"
66
"encoding/json"
7-
"fmt"
87
"net/url"
98

109
"github.com/arangodb/go-driver/v2/arangodb"
@@ -473,15 +472,17 @@ func convertToModelsAffected(allAffected []map[string]interface{}) []models.Affe
473472
return result
474473
}
475474

475+
// filepath: graphql/modules/releases/resolvers.go
476+
476477
// ResolveOrgAggregatedReleases aggregates release data by organization
477-
// FIXED: Removed runtime toLowerCase() conversion - org names are now stored lowercase
478+
// FIXED: Deduplicates vulnerability matches BEFORE calculating severity counts to ensure totals match
478479
func ResolveOrgAggregatedReleases(db database.DBConnection, severity string, username string) ([]interface{}, error) {
479480
ctx := context.Background()
480481
severityScore := util.GetSeverityScore(severity)
481482

482483
// Determine org filter based on authentication status
483-
userOrgs := []string{} // Initialize as empty slice, not nil
484-
filterByPublic := true // Default to public only
484+
userOrgs := []string{}
485+
filterByPublic := true
485486

486487
if username != "" {
487488
// User is authenticated - fetch their orgs from database
@@ -495,18 +496,14 @@ func ResolveOrgAggregatedReleases(db database.DBConnection, severity string, use
495496
var orgs []string
496497
_, readErr := cursor.ReadDocument(ctx, &orgs)
497498
if readErr == nil && orgs != nil {
498-
// Orgs are already stored lowercase - no conversion needed
499499
userOrgs = orgs
500500
}
501501
}
502502
}
503-
504-
// If user has no orgs specified, they have global access (empty orgs = see all)
503+
// If user has no orgs specified, they have global access
505504
filterByPublic = false
506505
}
507506

508-
fmt.Printf("User=%s\nOrgs=%v\n", username, userOrgs)
509-
510507
query := `
511508
FOR r IN release
512509
FILTER (
@@ -569,15 +566,19 @@ func ResolveOrgAggregatedReleases(db database.DBConnection, severity string, use
569566
}
570567
)
571568
572-
LET uniqueInstances = (
569+
// FIX: Deduplicate (CVE+Package) matches FIRST
570+
LET uniqueMatches = (
573571
FOR match IN cveMatches
574-
COLLECT cveId = match.cve_id, package = match.package
575-
RETURN 1
572+
COLLECT cveId = match.cve_id, package = match.package INTO groups = match
573+
// Since cveId is the same, the severity_rating will be the same for all in the group
574+
LET severity = groups[0].severity_rating
575+
RETURN { cveId, package, severity }
576576
)
577577
578+
// FIX: Calculate severity counts from the UNIQUE list, not the raw list
578579
LET severityCounts = (
579-
FOR match IN cveMatches
580-
COLLECT severity = match.severity_rating WITH COUNT INTO count
580+
FOR match IN uniqueMatches
581+
COLLECT severity = match.severity WITH COUNT INTO count
581582
RETURN { severity, count }
582583
)
583584
@@ -610,8 +611,8 @@ func ResolveOrgAggregatedReleases(db database.DBConnection, severity string, use
610611
RETURN {
611612
dependency_count: LENGTH(dependencyCount),
612613
synced_endpoint_count: syncCount,
613-
vulnerability_count: LENGTH(uniqueInstances),
614-
vulnerability_count_delta: prevVulnCount != null ? (LENGTH(uniqueInstances) - prevVulnCount) : null,
614+
vulnerability_count: LENGTH(uniqueMatches),
615+
vulnerability_count_delta: prevVulnCount != null ? (LENGTH(uniqueMatches) - prevVulnCount) : null,
615616
max_severity: LENGTH(cveMatches) > 0 ? MAX(cveMatches[*].severity_score) : 0,
616617
scorecard_score: latest.openssf_scorecard_score,
617618
severity_counts: severityCounts

0 commit comments

Comments
 (0)