Skip to content

CodeKeanu/cve-snoop

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CVE Snoop

A vulnerability intelligence dashboard that pulls CVE data from multiple official sources and presents it in a single pane of glass. Built for security analysts, VM teams, or anyone who wants a self-hosted way to stay on top of vulnerabilities without tab-switching between NVD, CISA KEV, and EPSS.

What It Does

  • Aggregates data from NVD, CISA KEV, EPSS, and CVE.org on configurable intervals
  • Normalizes everything into PostgreSQL so you can query across sources
  • Serves a React frontend with a customizable drag-and-drop dashboard (clickable stats that drill into the CVE list), a unified CVE query console (simple + expert modes), detailed CVE pages, and a side-by-side CVE comparison view
  • Lets analysts pin vendors and products to a personal watchlist — surfaces matching CVEs in a dedicated page and a dashboard widget; stored in browser local storage so each visitor gets their own
  • Pushes live updates over WebSocket as new data syncs in

Screenshots

Coming soon

Tech Stack

Layer Stack
Backend Python 3.12+, FastAPI, async SQLAlchemy (asyncpg), Alembic, APScheduler
Frontend React 18, TypeScript, Vite, TailwindCSS, React Query, Zustand, Recharts
Database PostgreSQL 16
Deployment Docker Compose

Quick Start

The fastest way to get running is with Docker Compose:

# Clone the repo
git clone https://github.com/codekeanu/cve-snoop.git
cd cve-snoop

# Set up your env (defaults work fine for local dev)
cp .env.example .env

# Build and run
docker compose up --build

Once everything is up:

On first startup, the backend kicks off an initial sync from all data sources. NVD is the big one and takes a while depending on whether you have an API key.

NVD API Key (Optional but Recommended)

Without an API key, NVD rate-limits you pretty hard. Grab a free one from NVD and drop it in your .env:

NVD_API_KEY=your-key-here

Local Development

If you want to work on the frontend or backend individually outside of Docker:

Backend

cd backend
pip install -e ".[dev]"
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

You'll still need a running PostgreSQL instance — easiest to just docker compose up db and point your DATABASE_URL at it.

Frontend

cd frontend
npm install
npm run dev

Vite dev server runs at http://localhost:5173 with hot reload.

Running Tests

# Backend (uses in-memory SQLite, no Postgres needed)
cd backend
pytest

# Frontend
cd frontend
npm run test

API Overview

All endpoints live under /api/v1. Here are the main ones:

Method Endpoint Description
GET /cves Paginated CVE list with search, sort, and filters (severity, vendor, product, KEV, EPSS, date range, exploit status)
GET /cves/{cve_id} Full CVE detail with CVSS, references, CPE, KEV, EPSS
GET /cves/{cve_id}/timeline Timeline of events for a CVE
GET /cves/{cve_id}/epss-history EPSS score history over time
GET /dashboard/summary Aggregated stats for the dashboard
POST /watchlist/matches Stateless: takes {entries: [{vendor, product?, label?}], days, limit} and returns recent CVEs matching any entry
GET /sync/status Current sync state for all data sources
POST /sync/{source}/trigger Manually kick off a sync (rate-limited)
POST /sync/kev/backfill Enrich every KEV CVE still missing NVD data (bypasses the per-run cap; single-flight)
GET /health Health check
WS /ws WebSocket feed for live CVE updates

Check out the full Swagger docs at /docs when the backend is running.

Data Sources

Source Default Interval What It Provides
NVD Every 2 hours CVE records, CVSS scores, references, weaknesses, CPE matches
CISA KEV Every 6 hours Known Exploited Vulnerabilities catalog
EPSS Daily Exploit Prediction Scoring System scores
CVE.org Every 4 hours Supplementary CVE data

All intervals are configurable via environment variables (SYNC_INTERVAL_NVD, etc.) in seconds.

The first NVD sync only pulls CVEs modified in the last 7 days, so older KEV catalog entries get created as stubs with no CVSS or references. Every KEV sync then fetches a batch of stubs from NVD's single-CVE endpoint (paced at the API rate limit) — KEV_ENRICH_PER_RUN caps each scheduled batch. To drain the entire stub queue in one shot, hit POST /sync/kev/backfill.

Project Structure

backend/
  app/
    main.py              # FastAPI app setup, lifespan, CORS
    config.py            # Pydantic settings (env-based)
    database.py          # Async SQLAlchemy engine + sessions
    models/              # ORM models
    schemas/             # Pydantic response schemas
    routers/             # API route handlers
    services/            # Business logic
    ingestion/           # Data source sync clients + scheduler
    ws/                  # WebSocket connection manager
  alembic/               # Database migrations
  tests/                 # pytest suite

frontend/
  src/
    pages/               # Dashboard, CVE list, CVE detail, CVE compare, watchlist
    components/          # UI components (layout, dashboard widgets, tables, feed)
    api/                 # Axios API client
    hooks/               # React Query hooks, WebSocket hook
    store/               # Zustand stores (live feed, dashboard layout, watchlist)
    types/               # TypeScript interfaces
    utils/               # Helpers (severity colors, date formatting)

Configuration

All configuration is done through environment variables. See .env.example for the full list. The key ones:

Variable Default Description
DATABASE_URL see .env.example PostgreSQL connection string
NVD_API_KEY (empty) NVD API key for higher rate limits
CORS_ORIGINS localhost:5173, localhost:3000 Allowed CORS origins
SYNC_INTERVAL_NVD 7200 NVD sync interval in seconds
SYNC_INTERVAL_KEV 21600 CISA KEV sync interval in seconds
SYNC_INTERVAL_EPSS 86400 EPSS sync interval in seconds
SYNC_INTERVAL_CVE_ORG 14400 CVE.org sync interval in seconds
KEV_ENRICH_PER_RUN 20 Max KEV stub CVEs to enrich from NVD each scheduled KEV sync. Each call is paced at the NVD rate limit; use POST /sync/kev/backfill to drain the full queue.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors