Given a newly disclosed vulnerability, Nightwatch answers three key questions:
- Which packages are exposed?
- How exploitable is the vulnerability?
- How far does the impact propagate across the dependency graph?
- Ingests advisories from GitHub Security Advisories (GHSA) across npm and PyPI
- Enriches CVEs with EPSS exploitation probability and CISA Known Exploited Vulnerabilities (KEV) membership
- Resolves precise affected version ranges using OSV.dev
- Traverses reverse dependency graphs to identify exposed downstream packages
- Calculates a composite Nightwatch Impact Score (NIS) for affected packages
- Generates per-CVE impact reports using Gemini or a structured fallback template
- Exposes results through a REST API with SSE progress streaming
- Returns D3-compatible blast-radius graph data for visualization
Nightwatch executes vulnerability analysis through an eight-stage LangGraph workflow.
| Step | Stage | Description |
|---|---|---|
| 1 | fetch_cves | Pull recent advisories from GHSA for npm and PyPI |
| 2 | triage | Rank by CVSS and priority tier, deduplicate per package, and retain top N advisories |
| 3 | enrich_cves | Fetch EPSS scores and check CISA KEV membership |
| 4 | resolve_packages | Resolve exact affected version ranges via OSV.dev |
| 5 | build_dep_graphs | Query deps.dev dependents and build reverse dependency graphs up to a configurable depth |
| 6 | score_impact | Compute NIS scores and fetch live package download counts |
| 7 | generate_reports | Generate impact reports using Gemini or a template fallback |
| 8 | persist | Persist jobs, CVEs, packages, and scores to Neon Postgres |
The Nightwatch Impact Score (NIS) is a weighted composite score designed to estimate the real-world impact of a vulnerability across an ecosystem.
Each component is normalized to a 0-10 scale before weighting.
NIS = (cvss × 0.20)
+ (epss × 0.25)
+ (kev × 0.15)
+ (criticality × 0.25)
+ (exposure × 0.15)
| Component | Weight | Raw Range | Normalization |
|---|---|---|---|
| CVSS | 20% | 0-10 | CVSS v3 base score used directly |
| EPSS | 25% | 0-1 | Multiplied by 10 |
| KEV | 15% | 0 or 3 | Fixed value if present in CISA KEV |
| Criticality | 25% | 0-10 | Download-based logarithmic normalization |
| Exposure | 15% | 0-10 | Reverse dependency graph depth weighting |
Criticality is derived from package popularity using weekly download counts.
log(downloads + 1) / log(20,000,000 + 1) × 10
The score is capped at 10 and normalized against a ceiling of 20 million weekly downloads, roughly matching the largest npm packages.
Examples:
- ~1,000,000 downloads/week → ~7.1
- ~10,000 downloads/week → ~4.7
Exposure reflects proximity to the vulnerable package within the dependency graph.
| Graph Depth | Score |
|---|---|
| 1 (direct dependent) | 10 |
| 2 | 5 |
| 3+ | 2 |
Direct dependents receive the highest score because they are most likely to consume the vulnerable package at runtime. Each additional hop reduces impact confidence.
KEV does not follow the standard 0-10 scale.
A package receives a fixed value of 3.0 if the vulnerability appears in the CISA Known Exploited Vulnerabilities catalog.
After weighting, this contributes up to 0.45 points to the final NIS score.
| Tier | NIS Range |
|---|---|
| CRITICAL | ≥ 8.5 |
| HIGH | ≥ 6.5 |
| MEDIUM | ≥ 4.0 |
| LOW | < 4.0 |
- npm and PyPI vulnerability scanning
- GHSA ingestion with package-level deduplication
- EPSS enrichment
- CISA KEV enrichment
- OSV.dev affected version resolution
- Reverse dependency graph generation via deps.dev
- NIS scoring and severity classification
- Blast-radius API with D3-compatible graph output
- Job queue with SSE progress streaming
- Gemini-generated reports with template fallback
- Neon Postgres persistence (SQLAlchemy + asyncpg)
- LangGraph checkpointing using Neon (psycopg3)
- Docker Compose deployment
- Frontend UI (
frontend/) - PyPI reverse dependency enrichment via libraries.io
- GitHub star count enrichment
- Alembic migrations
- Authentication and access control
nightwatch/
├── backend/ # FastAPI + LangGraph service
├── frontend/ # Web UI
└── docker-compose.yaml
backend/README.md- setup, configuration, and API referencefrontend/README.md- frontend setup and development