package alerts import ( "encoding/json" "strconv" "strings" ) // kevExposurePayload mirrors agent KEVScanReport JSON. type kevExposurePayload struct { ExposedCount int `json:"exposed_count"` CriticalCount int `json:"critical_count"` LikelyCount int `json:"likely_count"` RiskScore int `json:"risk_score"` Summary string `json:"summary"` Findings []struct { CVE string `json:"cve"` Name string `json:"name"` Status string `json:"status"` Severity string `json:"severity"` Detail string `json:"detail"` } `json:"findings"` } const EventKEVExposure = "kev_exposure" // NotifyKEVFromSysCheck parses a full_sys_check message and sends Telegram if enabled. func NotifyKEVFromSysCheck(n *Notifier, agentName, message string) { if n == nil || strings.TrimSpace(message) == "" { return } var report struct { KEV *kevExposurePayload `json:"kev_exposure"` } if err := json.Unmarshal([]byte(message), &report); err != nil || report.KEV == nil { return } k := report.KEV if k.ExposedCount == 0 && k.CriticalCount == 0 { return } s := n.settings() if !s.Events.KEVExposure { return } body := agentName + ": " + k.Summary if body == agentName+": " { body = agentName + ": KEV exposure indicators — exposed=" + strconv.Itoa(k.ExposedCount) + " critical=" + strconv.Itoa(k.CriticalCount) } for _, f := range k.Findings { if f.Status == "exposed" && f.Severity == "critical" { body += "\n• " + f.CVE + " " + f.Name } } n.Emit(EventKEVExposure, "AetherForge KEV alert", body) }