Tester reported only 4 hits for filter
exploitation_source='vulnrichment' AND exploitation_status != 'none'
while ssvc_technical_impact='total' returned 4682 and
ssvc_automatable='yes' returned 842 rows. Mismatch by orders of
magnitude.
Root cause: _apply_single_override only set vuln.exploitation_source
inside the CVSS and severity change blocks. SSVC writes
(exploitation_status, ssvc_technical_impact, ssvc_automatable) went
through their own branches without touching the source label. So a
CVE whose Wazuh CVSS happened to already match Vulnrichment got SSVC
fields written but exploitation_source stayed NULL.
Two-part fix:
1. _apply_single_override now sets exploitation_source whenever ANY
tracked field changed (single guard at the end of the function
replaces the two redundant assignments inside CVSS/severity blocks
— they still work because changes['has_changes'] is True there).
2. Migration 022 backfills exploitation_source='vulnrichment' on
every row that has ANY SSVC field populated but no source yet.
Idempotent. Existing nvd / cvelistv5 / manual source labels are
not touched (WHERE exploitation_source IS NULL).
After deploy + alembic upgrade head, the tester's filter will
return the real count (~840 SSVC-marked CVEs from vulnrichment,
not just the 4 with CVSS-diff coincidence).