What happens when a single npm package gets compromised?
A 3D interactive visualization of the npm ecosystem's single points of failure — backed by real vulnerability data from OSV.dev (217K+ records), real dependency graphs from deps.dev (1,087 packages), and autonomous investigation agents powered by Jac + Claude.
Live demo: supply-chain-frontend-nu.vercel.app
Built for JacHacks 2026 at the University of Michigan.
The default view renders 1,087 npm packages as a 3D force-directed graph. Each node is color-coded by blast radius (dependents x downloads) — red is critical, orange is high risk, cyan is safe. A leaderboard ranks the ecosystem's biggest chokepoints.
Click Investigate with Agents on any package. Five autonomous Jac walkers deploy simultaneously, each powered by Claude Haiku with by llm(tools=[...]):
| Agent | What it does |
|---|---|
| Vulnerability Scanner | Looks up CVEs, severity, affected versions |
| Blast Radius Analyzer | Traverses reverse deps to compute cascade impact |
| Dependency Auditor | Checks chain depth, transitive risk |
| Maintainer Risk | Evaluates ecosystem position, single-point-of-failure risk |
| Threat Synthesis | Combines all 4 findings into a strategic assessment |
Each agent autonomously decides which tool functions to call, reasons about results, and produces findings. The synthesis agent waits for all four specialists before producing the final report.
Curated replays of four real supply chain attacks with historical dependency edge injection:
- event-stream (2018) — Dependency hijack targeting Copay Bitcoin wallet
- ua-parser-js (2021) — Account takeover, cryptominer injection
- colors.js (2022) — Maintainer sabotage, infinite loop protest
- node-ipc (2022) — Geo-targeted protestware, CVSS 9.8
Paste any package.json or try preset demos (Express, PM2, Fastify). Cross-references your dependencies against 217K+ OSV vulnerability records. Vulnerable deps glow red in the graph, safe ones glow green.
After simulating a compromise, click AI Threat Report to generate a Claude-powered assessment of the attack's severity, blast radius, and recommended mitigations. Responses are permanently cached to minimize API costs.
Python data pipeline (SQLite)
-> data/risk_data.json (1,087 packages + 217K vulns + 4 scenarios)
-> Jac backend (walkers, graph traversal, by llm agents)
<- Frontend (Three.js + 3d-force-graph, single HTML file)
Backend: Written entirely in Jac. Package nodes, DependsOn edges, and walkers for graph traversal. Investigation agents use by llm(tools=[...]) — Claude Haiku autonomously calls Jac tool functions (lookup_vulns, compute_blast_radius, get_dependents, etc.) via the ReAct pattern.
Data pipeline: Python scripts fetch dependency graphs from deps.dev REST API, download OSV vulnerability data, compute risk scores, and export enriched JSON.
Frontend: Single HTML file, no build system. Three.js + 3d-force-graph for 3D visualization. Client-side fallback when backend is unavailable.
- Python 3.10+
- Jac (
pip install jaclang jac-scale byllm) - An Anthropic API key (for AI features)
# Clone
git clone https://github.com/drPod/supply-chain-risk-analyzer.git
cd supply-chain-risk-analyzer
# Run the data pipeline
bash scripts/setup_data.sh
# Set your API key
export ANTHROPIC_API_KEY=sk-ant-...
# Start the backend
jac start main.jac
# Open the frontend (separate terminal)
open frontend/index.html
# or serve it: python3 -m http.server 8080 --directory frontendThe frontend works without the backend — the 3D heatmap, scanner, and replays run client-side. The backend enables: simulate compromise via API, AI threat reports, and multi-agent investigation.
| Component | URL |
|---|---|
| Frontend | supply-chain-frontend-nu.vercel.app |
| Backend | supply-chain-api-production-458b.up.railway.app |
| Endpoint | Purpose |
|---|---|
build_graph(packages) |
Load package graph |
get_risk_heatmap(top_n) |
Top N packages by risk score |
get_blast_radius(package_name) |
Read-only cascade simulation |
infect_package(package_name) |
Simulate compromise (mutates graph) |
get_attack_scenarios() |
List curated attack scenarios |
load_scenarios(scenarios) |
Load scenario data |
reset_graph() |
Clear compromise state |
assess_compromise(...) |
AI-powered threat assessment |
| Endpoint | Agent |
|---|---|
investigate_vulns(package_name) |
Vulnerability Scanner |
investigate_blast(package_name) |
Blast Radius Analyzer |
investigate_deps(package_name) |
Dependency Auditor |
investigate_maintainer(package_name) |
Maintainer Risk Assessor |
investigate_synthesize(...) |
Threat Synthesis |
| Script | Purpose |
|---|---|
scripts/init_db.py |
Create SQLite schema |
scripts/fetch_bigquery.py |
Fetch dependency graphs from deps.dev (200+ seeds -> 1,087 packages) |
scripts/fetch_osv.py |
Download 217K+ npm vulnerability records from OSV.dev |
scripts/build_scenarios.py |
Insert curated attack scenarios with historical edges |
scripts/compute_risk.py |
Compute blast radius and risk scores |
scripts/export_json.py |
Export to data/risk_data.json |
main.jac # Entry point — imports all endpoints
services/
supply_chain.sv.jac # Core: Package/AttackScenario nodes, walkers, API
investigators.sv.jac # 5 investigation agents with by llm(tools=[...])
frontend/
index.html # Single-file frontend (Three.js + 3d-force-graph)
data/risk_data.json # Pre-built dataset for production
scripts/
setup_data.sh # Run the full data pipeline
fetch_bigquery.py # deps.dev dependency graph fetcher
fetch_osv.py # OSV vulnerability data downloader
build_scenarios.py # Famous attack scenario data
compute_risk.py # Risk score computation
export_json.py # JSON export for frontend
data/
risk_data.json # 1,087 packages + graph + vulns + scenarios
Jac, Jaseci, Python, JavaScript, Three.js, 3d-force-graph, Claude Haiku (Anthropic API), OSV.dev, deps.dev, Railway, Vercel, SQLite
MIT License. See LICENSE.