Plan M — close the "exploit-db is only a link, not in the score"
gap. Three new enrichment sources mapped per-CVE, written to
dedicated columns, displayed as badges, weighted in the priority
breakdown.
Schema (migration 025)
- vulnerabilities.exploit_db_ids (JSON list) + exploit_db_count
- vulnerabilities.pocs_github_urls (JSON list) + pocs_github_count
- vulnerabilities.metasploit_modules (JSON list) + metasploit_module_count
- vulnerabilities.exploit_intel_updated_at
- partial indexes on the *_count columns where > 0 for fast
"show me CVEs with exploits" filters.
Service (app/services/exploit_intel_service.py)
- fetch_exploit_db_cve_map(): downloads gitlab.com/exploit-database/
exploitdb/files_exploits.csv (cached 24h), parses CVE refs from
the `codes` column → {cve: [edb_id, ...]}.
- fetch_pocs_github_cve_map(): walks nomi-sec/PoC-in-GitHub yearly
folders via the GitHub contents API, builds {cve: [repo_url, ...]}.
- fetch_metasploit_cve_map(): downloads rapid7's
modules_metadata_base.json, extracts CVE refs per module.
- refresh_all_exploit_intel(): bulk writer, supports only_open + per-
source toggles, marks/clears counts so a removed reference doesn't
leave a stale flag behind.
Priority weighting
- New exploit signals folded into the existing max() block of
exploit_bonus:
metasploit_module_count > 0 → 4.5
exploit_db_count > 0 → 4.0
pocs_github_count > 0 → 2.5
exploit_source label expanded with metasploit / exploit_db /
poc_github so the breakdown UI shows which source drove the score.
API + Scheduler
- POST /api/v1/vulnerabilities/exploit-intel/refresh (editor) —
on-demand pull with `only_open`, `fetch_pocs`, `fetch_msf` flags.
- New nightly job at 03:45 UTC (between vulnrichment 03:00 + URS
04:00 so the score boost lands before URS recomputes).
Frontend
- Three list-row badges (MSF n / EDB n / PoC n) coloured red →
orange → yellow, ordered by weight, with tooltips.
- Vuln-detail page gets a "Public Exploit Catalogs" card under
Threat Intelligence — Metasploit module paths, clickable EDB-id
links to www.exploit-db.com, GitHub PoC links.
- "Exploit Intel" toolbar button next to EOL Check.
Out of scope (Plan N or later):
- GHSA integration (GitHub Security Advisory Database).
- Nuclei template count.
- Per-source toggles in Settings UI.
61 lines
2.3 KiB
Python
61 lines
2.3 KiB
Python
"""Add exploit-intel columns (Exploit-DB / PoC-in-GitHub / Metasploit)
|
|
|
|
Revision ID: 025
|
|
Revises: 024
|
|
Create Date: 2026-05-27 14:00:00.000000
|
|
|
|
Plan M foundation: explicit per-source exploit-availability columns
|
|
so the list endpoint can SQL-sort + filter, and the priority breakdown
|
|
can weight a CVE that has a real working exploit (not just KEV's
|
|
"observed in the wild" pointer).
|
|
|
|
Three nullable columns + denormalised counts. Future-proof for
|
|
PoC-in-GitHub + Metasploit (filled by separate enrichers later).
|
|
|
|
Idempotent — ADD COLUMN IF NOT EXISTS.
|
|
"""
|
|
from alembic import op
|
|
|
|
|
|
revision = "025"
|
|
down_revision = "024"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.execute("""
|
|
ALTER TABLE vulnerabilities
|
|
ADD COLUMN IF NOT EXISTS exploit_db_ids TEXT,
|
|
ADD COLUMN IF NOT EXISTS exploit_db_count INTEGER DEFAULT 0,
|
|
ADD COLUMN IF NOT EXISTS pocs_github_urls TEXT,
|
|
ADD COLUMN IF NOT EXISTS pocs_github_count INTEGER DEFAULT 0,
|
|
ADD COLUMN IF NOT EXISTS metasploit_modules TEXT,
|
|
ADD COLUMN IF NOT EXISTS metasploit_module_count INTEGER DEFAULT 0,
|
|
ADD COLUMN IF NOT EXISTS exploit_intel_updated_at TIMESTAMP;
|
|
""")
|
|
# Indexes for filter/sort on "show me CVEs with public exploits"
|
|
op.execute("""
|
|
CREATE INDEX IF NOT EXISTS ix_vulnerabilities_exploit_db_count
|
|
ON vulnerabilities (exploit_db_count) WHERE exploit_db_count > 0;
|
|
""")
|
|
op.execute("""
|
|
CREATE INDEX IF NOT EXISTS ix_vulnerabilities_metasploit_count
|
|
ON vulnerabilities (metasploit_module_count) WHERE metasploit_module_count > 0;
|
|
""")
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.execute("DROP INDEX IF EXISTS ix_vulnerabilities_exploit_db_count;")
|
|
op.execute("DROP INDEX IF EXISTS ix_vulnerabilities_metasploit_count;")
|
|
op.execute("""
|
|
ALTER TABLE vulnerabilities
|
|
DROP COLUMN IF EXISTS exploit_db_ids,
|
|
DROP COLUMN IF EXISTS exploit_db_count,
|
|
DROP COLUMN IF EXISTS pocs_github_urls,
|
|
DROP COLUMN IF EXISTS pocs_github_count,
|
|
DROP COLUMN IF EXISTS metasploit_modules,
|
|
DROP COLUMN IF EXISTS metasploit_module_count,
|
|
DROP COLUMN IF EXISTS exploit_intel_updated_at;
|
|
""")
|