ENISA's bare /exploitedvulnerabilities endpoint returns a curated 4-entry
"recent" widget, not the full catalog. The actual full catalog lives at
/api/search?exploited=true (1500+ CVEs, paginated).
Also fix date parsing — ENISA returns 'Apr 29, 2026, 3:10:37 PM' style,
not ISO. Try multiple formats, fall back to raw string when unknown.
Prefer exploitedSince over datePublished as date_added when available.
Parser now correctly handles ENISA item shape (aliases as newline-separated
string, not array).
EUVD (EU Vulnerability Database, ENISA) integration as second
authoritative catalog alongside CISA KEV. EU-Compliance use cases
benefit from a non-US source; CVEs confirmed by both catalogs get
the highest priority via score stacking.
Two ENISA endpoints are merged into one cached map (24h TTL):
- /exploitedvulnerabilities (analogous to CISA KEV)
- /criticalvulnerabilities (ENISA Critical flag)
Priority-Score formula:
- Exploit-Signal now triggered by KEV OR EUVD listing
- Catalog-Bonus stacking: KEV +10, EUVD +10, KEV-ransomware +5,
EU-Critical +3. A CVE in both catalogs adds +20 base.
CPR Score (Cybersecurity Priority Risk = CVSS x EPSS x 10) added
as separate metric next to Priority, per JacquesKruger/EPSS-Server
convention. Calculated on-the-fly, no DB column needed.
New API filters: euvd_only, eu_critical, in_any_catalog,
in_both_catalogs. Setting toggle enrichment_euvd_enabled (default true).
Frontend: new EUVD column (blue badge, EU-CRIT sub-badge), CPR column
with mini-bar, four catalog filter checkboxes. Detail page splits
threat intel into CISA KEV / ENISA EUVD / EPSS sections; breakdown
shows EUVD bonus row and CPR score with both-catalogs hint.
Add a settings-page dropdown (Critical / High+ / Medium+ / Low+) that
controls which severities trigger a 'new vulnerability' email during
Wazuh sync. Stored in the existing settings KV table under
'notification_min_severity', default 'critical' (no behaviour change
on upgrade).
Backend:
- email_service.should_notify_for_severity(db, severity) reads the
threshold from settings and compares using a severity rank.
- Both sync paths in vulnerabilities.py now delegate to the helper
instead of the hard-coded 'critical only' check (the comment
already lied about 'CRITICAL or HIGH').
Frontend:
- New control in the Notification Settings section, persists via the
generic /api/v1/settings/{key} PUT endpoint.
Risk score now pulls from multiple threat intel sources instead of
only AI/CVSS data:
- EPSS (FIRST.org) — probability of exploitation in next 30 days
- CISA KEV — known actively exploited vulnerabilities (with ransomware flag)
- Existing Wazuh exploit flags as fallback
Adds DB columns (epss_score, epss_percentile, kev_listed, kev_*,
enrichment_sources, enrichment_updated_at), an enrichment_service
with cached KEV catalog (24h TTL in settings table) and batched
EPSS lookups, manual + bulk + KEV-refresh endpoints, automatic
enrichment after Wazuh sync, and a daily scheduler job to refresh
scores.
Frontend gets KEV badges, EPSS column with percentile, KEV-only +
EPSS-min filters, a "Refresh Threat Intel" button, and a priority
score breakdown card on the detail page.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Perf:
- AppShell: auth check once on mount instead of every pathname change
- Dashboard: replace bare <a> with Next Link for prefetch
Security:
- Migrate python-jose to PyJWT (CVE-2024-33663, CVE-2024-33664)
- JWT exp/iat now UTC-aware via datetime.now(timezone.utc)
- Drop default 'changeme' fallback for DEFAULT_ADMIN_PASSWORD
- Force POSTGRES_PASSWORD env in docker-compose
- Add Wazuh severity string as fallback when CVSS score is missing,
preventing critical vulns from being classified as "none"
- Fix solved-filter to check only the LATEST alert status per CVE
instead of filtering all CVEs that were ever solved (fixes re-emerged
vulns being incorrectly hidden)
- Try both score.base and score.base_score for indexer compatibility
- Add detailed sync logging (severity breakdown, new/updated counts)
- Show time alongside date for detected_at in frontend and PDF reports