Skip to content

Commit 792d234

Browse files
committed
fix(039): consistent threat counts in Security tab
AggregateReports now classifies findings before summarizing. ReportSummary includes dangerous/warnings/info_level counts. Frontend reads summary from API response. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 7229fb5 commit 792d234

27 files changed

Lines changed: 214 additions & 12 deletions

frontend/src/types/api.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,25 @@ export interface SecurityScanReport {
6767
risk_score: number
6868
findings: SecurityScanFinding[]
6969
finding_counts: SecurityScanFindingCounts
70+
summary: SecurityScanReportSummary
7071
scanned_at: string
7172
duration_ms?: number
7273
scanners_used?: string[]
7374
}
7475

76+
// Summary from the aggregated report API (matches Go ReportSummary)
77+
export interface SecurityScanReportSummary {
78+
critical: number
79+
high: number
80+
medium: number
81+
low: number
82+
info: number
83+
total: number
84+
dangerous: number // Threat level counts
85+
warnings: number
86+
info_level: number
87+
}
88+
7589
// Server types
7690
export interface Server {
7791
name: string

frontend/src/views/ServerDetail.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -565,25 +565,25 @@
565565
<div class="stats shadow bg-base-100">
566566
<div class="stat py-3 px-4">
567567
<div class="stat-title text-xs">Dangerous</div>
568-
<div class="stat-value text-lg text-error">{{ scanReport.finding_counts?.dangerous ?? 0 }}</div>
568+
<div class="stat-value text-lg text-error">{{ scanReport.summary?.dangerous ?? 0 }}</div>
569569
</div>
570570
</div>
571571
<div class="stats shadow bg-base-100">
572572
<div class="stat py-3 px-4">
573573
<div class="stat-title text-xs">Warnings</div>
574-
<div class="stat-value text-lg text-warning">{{ scanReport.finding_counts?.warning ?? 0 }}</div>
574+
<div class="stat-value text-lg text-warning">{{ scanReport.summary?.warnings ?? 0 }}</div>
575575
</div>
576576
</div>
577577
<div class="stats shadow bg-base-100">
578578
<div class="stat py-3 px-4">
579579
<div class="stat-title text-xs">Info</div>
580-
<div class="stat-value text-lg text-info">{{ scanReport.finding_counts?.info ?? 0 }}</div>
580+
<div class="stat-value text-lg text-info">{{ scanReport.summary?.info_level ?? 0 }}</div>
581581
</div>
582582
</div>
583583
<div class="stats shadow bg-base-100">
584584
<div class="stat py-3 px-4">
585585
<div class="stat-title text-xs">Total</div>
586-
<div class="stat-value text-lg">{{ scanReport.finding_counts?.total ?? 0 }}</div>
586+
<div class="stat-value text-lg">{{ scanReport.summary?.total ?? 0 }}</div>
587587
</div>
588588
</div>
589589
</div>

internal/security/scanner/engine.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,9 @@ func AggregateReports(jobID, serverName string, reports []*ScanReport) *Aggregat
427427
agg.Reports = append(agg.Reports, *r)
428428
}
429429

430+
// Classify findings that lack threat_type/threat_level (legacy data)
431+
ClassifyAllFindings(agg.Findings)
432+
430433
agg.RiskScore = CalculateRiskScore(agg.Findings)
431434
agg.Summary = SummarizeFindings(agg.Findings)
432435
return agg

internal/security/scanner/sarif.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ func CalculateRiskScore(findings []ScanFinding) int {
280280
func SummarizeFindings(findings []ScanFinding) ReportSummary {
281281
summary := ReportSummary{Total: len(findings)}
282282
for _, f := range findings {
283+
// Count by CVSS severity
283284
switch f.Severity {
284285
case SeverityCritical:
285286
summary.Critical++
@@ -292,6 +293,15 @@ func SummarizeFindings(findings []ScanFinding) ReportSummary {
292293
case SeverityInfo:
293294
summary.Info++
294295
}
296+
// Count by user-facing threat level
297+
switch f.ThreatLevel {
298+
case ThreatLevelDangerous:
299+
summary.Dangerous++
300+
case ThreatLevelWarning:
301+
summary.Warnings++
302+
case ThreatLevelInfo:
303+
summary.InfoLevel++
304+
}
295305
}
296306
return summary
297307
}

internal/security/scanner/types.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,17 @@ type AggregatedReport struct {
145145
Reports []ScanReport `json:"reports"`
146146
}
147147

148-
// ReportSummary provides counts by severity
148+
// ReportSummary provides counts by severity and threat level
149149
type ReportSummary struct {
150-
Critical int `json:"critical"`
151-
High int `json:"high"`
152-
Medium int `json:"medium"`
153-
Low int `json:"low"`
154-
Info int `json:"info"`
155-
Total int `json:"total"`
150+
Critical int `json:"critical"`
151+
High int `json:"high"`
152+
Medium int `json:"medium"`
153+
Low int `json:"low"`
154+
Info int `json:"info"`
155+
Total int `json:"total"`
156+
Dangerous int `json:"dangerous"` // Threat level: tool poisoning, prompt injection
157+
Warnings int `json:"warnings"` // Threat level: rug pull, high CVEs
158+
InfoLevel int `json:"info_level"` // Threat level: low CVEs, informational
156159
}
157160

158161
// IntegrityBaseline represents the approved integrity state for a server

web/frontend/dist/assets/Activity-CBaueec_.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/frontend/dist/assets/AdminDashboard-DvFmEAsN.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/frontend/dist/assets/AdminServers-F01G__py.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)