Files
vulncheck/alembic/versions/025_add_exploit_intel_columns.py
T
vulncheck e656701293 feat(exploit-intel): public exploit catalogs (EDB / PoC-in-GitHub / Metasploit)
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.
2026-05-27 18:49:13 +02:00

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;
""")