## https://sploitus.com/exploit?id=BE5AEF42-6F46-5529-A605-988CA2C73D8D
# ExploitAtlas
A full-stack Rust application for CVE intelligence gathering, attack path visualization, and multi-source exploit enrichment. Built with **Axum** (backend), **Yew/WASM** (frontend), **SQLite**, **Cytoscape.js**, and **Chart.js**, packaged in a single Docker image.
ExploitAtlas pulls data from six external sources โ MITRE CVE, NVD, FIRST.org EPSS, GitHub, Exploit-DB, and Nuclei templates โ to build a unified threat profile for any CVE. It extracts real exploitation commands from PoC repository READMEs and renders them with copy-to-clipboard buttons.
## Quick Start
```bash
docker compose up --build
# Open http://localhost:3000
```
That's it. The Docker image builds both backend and frontend, installs fonts for PDF generation, and runs a self-contained server on port 3000.
## Features
### CVE Search & Analysis
Enter any CVE ID (e.g. `CVE-2021-44228`, `2024-6387`, or just `6387`) into the search bar. The input accepts partial IDs โ the system normalizes them to the standard `CVE-YYYY-NNNNN` format automatically. A set of well-known CVEs (Log4Shell, EternalBlue, PrintNightmare, PwnKit, regreSSHion, and others) appears as clickable suggestions below the input.
### Multi-Source Enrichment Pipeline
When you analyze a CVE, the backend runs a parallel enrichment pipeline across six data sources:
1. **MITRE CVE API** โ Primary source for CVE metadata: summary text, CVSS v3.1/v3.0/v2.0 scores, CVSS vector components, affected vendor/product/version lists, and reference URLs. This is the authoritative source for the vulnerability description and the starting point for everything else.
2. **NVD (National Vulnerability Database)** โ Fetched from `services.nvd.nist.gov/rest/json/cves/2.0`. Provides CWE weakness identifiers (mapped to human-readable names via a built-in lookup table covering ~45 common CWEs), CVSS v3.1 base score and vector string, and CPE 2.3 match URIs (up to 20). If MITRE has no CVSS score but NVD does, the NVD score is used. An optional `NVD_API_KEY` environment variable enables higher rate limits.
3. **FIRST.org EPSS (Exploit Prediction Scoring System)** โ Fetched from `api.first.org/data/v1/epss`. Returns the real-world exploitation probability score (0.0โ1.0), percentile ranking, and data date. When the API is available, this replaces the built-in heuristic estimator. When it fails, the heuristic (based on CVSS score and KEV membership) is used as a fallback.
4. **GitHub PoC Repository Search** โ Searches GitHub for `{CVE_ID} PoC` repositories, sorted by star count. Returns the top 5 results with repo name, URL, description, stars, and primary language. For the top 3 repos by stars, the backend also fetches each README via the GitHub Contents API (`application/vnd.github.raw`), extracts all fenced code blocks (language tag, code content, and up to 200 characters of preceding context text), and truncates the full README to 15KB.
5. **Exploit-DB** โ Searches the `offensive-security/exploitdb` mirror on GitHub using code search (`q={CVE_ID}+repo:offensive-security/exploitdb+path:exploits`). Extracts EDB IDs from filenames, infers platform and exploit type from file paths, and builds direct links to `exploit-db.com/exploits/{EDB_ID}`. If GitHub code search fails (rate limits), falls back to GitLab's API on `gitlab.com/exploit-database/exploitdb`. Returns up to 5 entries.
6. **Nuclei Templates** โ Searches `projectdiscovery/nuclei-templates` on GitHub for YAML files mentioning the CVE ID. For the top 3 results, fetches the raw YAML from `raw.githubusercontent.com` and parses `id:`, `info.name:`, and `info.severity:` fields using simple line-based string parsing (no YAML library dependency). The full template YAML is stored and can be expanded in the UI with a copy button.
The pipeline is organized into two parallel batches to minimize latency:
- **Batch 1** (parallel): MITRE + NVD + EPSS
- **Batch 2** (parallel): GitHub PoCs + Exploit-DB + Nuclei
- **Sequential**: PoC README fetching (depends on batch 2 results)
Each source has its own timeout (8โ15 seconds) and fails gracefully โ a failed NVD lookup doesn't block the analysis, the data just won't be present.
### Severity Scoring
CVSS scores are extracted directly from the MITRE CVE data (preferring v3.1 > v3.0 > v2.0). When no CVSS score is available in the CVE record, the system predicts severity from the description text using keyword matching: RCE maps to 9.8, privilege escalation to 8.8, SQL injection to 8.5, XSS to 6.5, DoS to 5.0, and so on.
CVSS v3.1 vector components (Attack Vector, Attack Complexity, Privileges Required, User Interaction, Scope, Confidentiality/Integrity/Availability Impact) are extracted and used to build the attack flow graph.
### CISA KEV Integration
The full CISA Known Exploited Vulnerabilities catalog is loaded into memory at startup and refreshed every 30 minutes via a background Tokio task. Each analyzed CVE is checked against this cache. The frontend shows KEV status as a metric card and highlights KEV entries in the live feed.
### Attack Path Visualization
The system detects the vulnerability category from the CVE summary, reference URLs, and CVE ID (with special-case detection for Log4Shell, EternalBlue, PrintNightmare, Confluence OGNL, PwnKit, and Fortinet VPN bypass) and generates a directed attack flow graph. When CVSS vector components are available, the graph nodes are annotated with the specific CVSS metric, its value, and a risk level (critical/high/medium/low) with color coding. The graph is rendered interactively using Cytoscape.js with click-to-inspect node detail panels.
Ten vulnerability categories are supported:
| Category | Nodes |
|----------|-------|
| SQL Injection | Attacker โ Frontend โ SQL Query โ Database โ Impact |
| Cross-Site Scripting | Attacker โ Browser โ Web Page โ Injected JS โ Impact |
| Remote Code Execution | Attacker โ Network โ Vulnerable Service โ RCE โ Impact |
| Privilege Escalation | Attacker โ Low-Priv Account โ Vuln Component โ Privesc โ Impact |
| Directory Traversal | Attacker โ Web Input โ Path Handling โ Files Read โ Impact |
| Insecure Deserialization | Attacker โ Serialized Data โ Deser Logic โ Code Exec โ Impact |
| Memory Corruption | Attacker โ Vuln Parser โ Memory Corruption โ Hijack โ Impact |
| Auth Bypass | Attacker โ Auth Layer โ Bypass โ Unauthorized Access โ Impact |
| Information Disclosure | Attacker โ Endpoint โ Data Exposure โ Impact |
| Generic *(fallback)* | Attacker โ Entry Point โ Vuln Component โ Impact |
### Exploitation Commands & PoC Details
Code blocks extracted from PoC repository READMEs are displayed in the EXPLOITATION COMMANDS section with syntax-highlighted `` blocks, a language tag pill, and a copy-to-clipboard button. Clicking copy writes the code content to the system clipboard and shows a "Copied!" confirmation for 2 seconds.
Each PoC repository is shown as a collapsible card with the repo name (linking to GitHub), star count, language pill, extracted code blocks, and a "View full README" toggle that expands the truncated README content.
### Nuclei Detection Templates
Nuclei YAML templates matching the CVE are displayed with template ID, name, and severity badge. Each template has an expandable section showing the full YAML with a copy button, useful for quick integration into scanning workflows.
### CWE Weakness Classification
When NVD data is available, CWE identifiers are displayed in the WEAKNESS CLASSIFICATION section under the intel briefing. Each CWE ID is mapped to its human-readable name (e.g., "CWE-79: Cross-site Scripting (XSS)") using a built-in lookup table covering approximately 45 of the most common CWE entries.
### Exploit-DB Entries
Exploit-DB results are shown in the INTELLIGENCE SOURCES panel as a structured table with EDB ID (linking to exploit-db.com), title, platform, and exploit type. When no indexed results are found, a direct search link to Exploit-DB is provided.
### PDF Reports
Downloadable PDF reports are generated server-side using `genpdf` with Liberation/DejaVu fonts. Each report contains: CVE overview (ID, severity, EPSS, vendor, dates, KEV status), technical summary and category, exploitation steps, affected products (top 20), and references (top 15). Unicode characters are substituted for PDF compatibility.
### Session Analytics (Telemetry Page)
The `/analytics` route displays three Chart.js visualizations:
- **Temporal Distribution** โ Line chart of analyzed CVEs by publication year
- **Vendor Exposure** โ Bar chart of top 8 affected vendors
- **Geo Attribution** โ Bar chart mapping vendors to countries using a built-in lookup table (20 major vendors mapped to their headquarters country)
### Real-Time Updates
A WebSocket connection (`/ws`) pushes analysis results and KEV refresh notifications to all connected browsers. When one user analyzes a CVE, all open sessions receive the updated data. The broadcast uses a Tokio broadcast channel with capacity 128.
### Live KEV Feed
The CISA KEV feed panel shows recent entries (5 compact, 12 expanded) with CVE ID, KEV badge, vendor/product, description, and date added. Each entry links to NVD and the CISA KEV catalog.
### Rate Limiting
Two rate limiters (via `tower_governor`) protect the API:
- **Analyze endpoint** (`POST /api/cves/analyze`): 1 request per 6 seconds, burst of 10, per IP
- **Read endpoints** (all `GET /api/*`): 1 request per second, burst of 60, per IP
## Architecture
```
Browser (WASM) Backend (Axum)
โโโโโโโโโโโโโโโโ REST / WS โโโโโโโโโโโโโโโโโโโโ
โ Yew SPA โ โโโโโโโโโโโโโโบ โ API handlers โ
โ Cytoscape.jsโ โ Services layer โโโโบ MITRE CVE API
โ Chart.js โ โ SQLite cache โโโโบ NVD API (v2.0)
โโโโโโโโโโโโโโโโ โ WS broadcaster โโโโบ FIRST.org EPSS API
โ Rate limiter โโโโบ GitHub Search API
โ KEV cache โโโโบ Exploit-DB (GitHub/GitLab)
โ PDF generator โโโโบ Nuclei Templates (GitHub)
โโโโโโโโโโโโโโโโโโโโโโโบ CISA KEV Feed
```
The backend is a single Axum server binary. It serves the frontend SPA (compiled to WASM by Trunk) as static files, handles all API routes, manages WebSocket connections, and runs background tasks (KEV refresh). All enriched CVE data is serialized as JSON into a `raw_json` column in SQLite, ensuring backward compatibility โ old cached records missing new fields deserialize cleanly via `#[serde(default)]`.
## API Routes
| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/health` | Health check (`ok` or `degraded` based on DB connectivity) |
| `GET` | `/api/cves` | List all cached CVEs (params: `limit`, `offset`; max 200) |
| `GET` | `/api/cves/:id` | Get CVE detail (fetches from MITRE if not cached) |
| `POST` | `/api/cves/analyze` | Full multi-source analysis: fetch + enrich + store + broadcast |
| `GET` | `/api/cves/:id/pdf` | Download PDF report |
| `GET` | `/api/graph` | All cached CVEs as a Cytoscape.js-compatible graph |
| `GET` | `/api/kev` | Latest 50 CISA KEV entries sorted by date |
| `GET` | `/api/stats` | Dashboard statistics (total, critical, high counts, recent 6) |
| `GET` | `/ws` | WebSocket for real-time push notifications |
| `GET` | `/*` | Serves the frontend SPA (fallback to `index.html`) |
## Project Structure
```
ExploitAtlas/
โโโ Cargo.toml # Workspace root (members: shared, backend, frontend)
โโโ Cargo.lock # Pinned dependency versions
โโโ Dockerfile # Multi-stage: build backend, build frontend, runtime
โโโ docker-compose.yml # One-command deployment with persistent volume
โโโ .env.example # Environment variable reference
โโโ .gitignore
โ
โโโ migrations/
โ โโโ 20240101000000_init.sql # SQLite schema (cves, attack_templates, github_pocs)
โ
โโโ shared/ # Shared library crate (used by both backend and frontend)
โ โโโ Cargo.toml # Dependencies: serde, serde_json
โ โโโ src/lib.rs # All domain types, constants, and helpers:
โ CveRecord, AttackTemplate, AttackNode, AttackEdge,
โ CvssComponents, SeverityInfo, GitHubPoC, KevEntry,
โ CodeBlock, PocDetail, NvdData, CweEntry, EpssData,
โ ExploitDbEntry, NucleiTemplate,
โ GraphResponse, GraphElements, CyNode, CyEdge,
โ WsMessage, AnalyzeRequest/Response, CveListResponse,
โ KevFeedResponse, DashboardStats, CveSummary,
โ normalize_cve_id(),
โ POPULAR_CVES, VENDOR_COUNTRY_MAP, PATCH_VENDOR_KEYWORDS
โ
โโโ backend/ # Axum server crate
โ โโโ Cargo.toml # Dependencies listed in "Dependencies" section below
โ โโโ src/
โ โโโ main.rs # Server startup, router, CORS, rate limiters, background tasks
โ โโโ config.rs # Reads HOST, PORT, DATABASE_URL, GITHUB_TOKEN, NVD_API_KEY,
โ โ STATIC_DIR, ALLOWED_ORIGIN from environment
โ โโโ db.rs # SQLite pool initialization + migration runner
โ โโโ errors.rs # AppError enum (BadRequest, External, Internal, NotFound)
โ โ mapped to HTTP JSON error responses
โ โโโ models.rs # sqlx FromRow structs: CveRow, AttackTemplateRow, GithubPocRow
โ โโโ handlers/
โ โ โโโ mod.rs
โ โ โโโ cve.rs # All CVE endpoints: health, list, get, analyze, pdf, kev, stats
โ โ โ Contains the parallel enrichment pipeline orchestration
โ โ โโโ graph.rs # Cytoscape.js-compatible graph endpoint
โ โ โโโ ws.rs # WebSocket upgrade handler
โ โโโ services/
โ โ โโโ mod.rs
โ โ โโโ mitre.rs # MITRE CVE API: fetch_and_enrich(), parse_cve_data(),
โ โ โ extract_cvss_components()
โ โ โโโ kev.rs # CISA KEV: KevCache with Arc, refresh(), contains()
โ โ โโโ severity.rs # get_severity_label(), predict_severity_from_text()
โ โ โโโ epss.rs # predict_epss_score() heuristic based on CVSS + KEV
โ โ โโโ epss_api.rs # fetch_epss() from FIRST.org API (real EPSS scores)
โ โ โโโ nvd.rs # fetch_nvd_data() from NVD API v2.0 (CWE, CVSS, CPE)
โ โ โโโ github_poc.rs # search_github_pocs() โ GitHub repository search
โ โ โโโ poc_readme.rs # fetch_poc_details() โ README fetching + code block extraction
โ โ โโโ exploit_db.rs # search_exploit_db() โ GitHub/GitLab code search on exploitdb
โ โ โโโ nuclei.rs # search_nuclei_templates() โ GitHub code search + YAML fetch
โ โ โโโ attack_path.rs # detect_category() + build_attack_template() (10 categories)
โ โ โโโ pdf.rs # generate_pdf_report() via genpdf (Liberation/DejaVu fonts)
โ โโโ ws/
โ โโโ mod.rs
โ โโโ broadcaster.rs # Tokio broadcast channel (capacity 128) for WS push
โ
โโโ frontend/ # Yew WASM SPA crate
โ โโโ Cargo.toml # Dependencies listed in "Dependencies" section below
โ โโโ Trunk.toml # Trunk build config (dev proxy to backend on :3000)
โ โโโ index.html # HTML shell: loads Cytoscape.js + Chart.js from /static/
โ โโโ src/
โ โโโ main.rs # Yew renderer entry point
โ โโโ app.rs # Root component: state management (current_cve, history,
โ โ kev_entries, loading, error), WS connection, KEV load, routing,
โ โ conditional rendering of pre-search dashboard vs post-search layout
โ โโโ router.rs # Yew Router: / (Home), /analytics (Telemetry), /404
โ โโโ bindings/
โ โ โโโ mod.rs
โ โ โโโ cytoscape.rs # wasm_bindgen extern: initCytoscape() for graph rendering
โ โ โโโ chartjs.rs # wasm_bindgen extern: createChart() for Chart.js
โ โโโ services/
โ โ โโโ mod.rs
โ โ โโโ api.rs # HTTP calls: analyze_cve(), list_cves(), get_graph(),
โ โ โ get_kev_feed(), get_stats(), pdf_url()
โ โ โโโ websocket.rs # WS client: auto ws/wss detection, JSON parsing, Yew callback
โ โโโ components/
โ โโโ mod.rs
โ โโโ header.rs # Nav bar: CortexSec branding, Recon/Telemetry tabs, credits
โ โโโ search_bar.rs # CVE input with auto-normalization and POPULAR_CVES suggestions
โ โโโ metric_cards.rs # 5 metric cards: Target ID, Threat Score (with NVD comparison),
โ โ Severity Rating, Exploit Probability (real EPSS or heuristic
โ โ with source label), KEV Status
โ โโโ cve_summary.rs # Intel Briefing (summary), Weakness Classification (CWE from NVD),
โ โ Attack Surface Inventory (products), Chronology (dates)
โ โโโ references_panel.rs # Intelligence Sources (refs), Vendor Advisories (patches),
โ โ Exploit Artifacts (GitHub PoCs), Exploit-DB Entries
โ โโโ attack_graph.rs # Cytoscape.js wrapper: renders attack flow, click-to-inspect nodes
โ โโโ attack_steps.rs # Attack Sequence (steps), Exploitation Commands (code blocks
โ โ from PoC READMEs with copy buttons), PoC Repositories
โ โ (collapsible cards with README), Detection Templates (Nuclei
โ โ YAML with copy buttons), Countermeasures
โ โโโ code_block.rs # Reusable code block: with language pill,
โ โ copy-to-clipboard button (web_sys Clipboard API), 2s "Copied!"
โ โโโ charts.rs # Chart.js: Temporal Distribution, Vendor Exposure, Geo Attribution
โ โโโ kev_feed.rs # Live KEV feed: compact (5) or expanded (12) entries
โ โโโ pdf_download.rs # PDF download button linking to /api/cves/{id}/pdf
โ โโโ threat_dashboard.rs # Pre-search landing: threat metrics, high-value targets,
โ recent intel
โ
โโโ frontend/static/
โโโ style.css # Terminal dark theme (JetBrains Mono, #050505 bg, #00d26a accent)
โ Glass cards, severity pills, metric cards, hero banner,
โ code blocks with copy buttons, PoC detail cards, Nuclei cards,
โ CWE entries, Exploit-DB rows, collapsible toggles,
โ animations (fadeSlideUp, pulseGlow, scanline, shimmer),
โ responsive breakpoints at 1024px, 900px, 640px
โโโ cytoscape.min.js # Vendored Cytoscape.js v3.30
โโโ chart.min.js # Vendored Chart.js v4.4
```
## Database Schema
SQLite with three tables (auto-created via migration on startup):
```sql
-- Full CVE data stored as JSON blob for forward/backward compatibility
cves (
id TEXT PRIMARY KEY, -- "CVE-2021-44228"
raw_json TEXT NOT NULL, -- Full serialized CveRecord (all enrichment data)
summary TEXT, -- Indexed for listing
cvss REAL,
severity TEXT,
epss REAL,
in_kev INTEGER,
vendor TEXT,
published TEXT,
modified TEXT,
category TEXT,
created_at TEXT DEFAULT now()
)
-- Attack flow graph data
attack_templates (
cve_id TEXT PRIMARY KEY โ cves(id),
category TEXT,
nodes TEXT, -- JSON array of AttackNode
edges TEXT, -- JSON array of AttackEdge
steps TEXT -- JSON array of strings
)
-- GitHub PoC repositories
github_pocs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
cve_id TEXT โ cves(id),
name TEXT,
url TEXT,
description TEXT,
stars INTEGER,
language TEXT
)
```
New enrichment data (NVD, EPSS, Exploit-DB, Nuclei, PoC details) is stored inside the `raw_json` column as part of the serialized `CveRecord`. Old cached records without these fields deserialize correctly because all new fields use `#[serde(default)]`.
## Configuration
Set via environment variables (see `.env.example`):
| Variable | Default | Description |
|----------|---------|-------------|
| `HOST` | `0.0.0.0` | Bind address |
| `PORT` | `3000` | Server port |
| `DATABASE_URL` | `sqlite:data.db?mode=rwc` | SQLite connection string |
| `GITHUB_TOKEN` | *(none)* | GitHub PAT โ increases rate limits from 10/min to 30/min for code search (used by PoC search, Exploit-DB, Nuclei, README fetching) |
| `NVD_API_KEY` | *(none)* | NVD API key โ increases rate limits from 5/30s to 50/30s. Request one at https://nvd.nist.gov/developers/request-an-api-key |
| `STATIC_DIR` | `./dist` | Path to frontend build output |
| `ALLOWED_ORIGIN` | *(derived)* | CORS origin. If unset, derived from `http://{HOST}:{PORT}` |
| `RUST_LOG` | `backend=info` | Log level filter (`tracing_subscriber` EnvFilter syntax) |
## Dependencies
### System Requirements
- **Docker** (recommended) โ Docker 20.10+ and Docker Compose v2
- Or for local development:
- **Rust** 1.85+ (edition 2021 workspace, some dependencies require recent Rust)
- **Trunk** โ `cargo install trunk --locked` (WASM build tool for Yew)
- **wasm32 target** โ `rustup target add wasm32-unknown-unknown`
- No other system dependencies (SQLite is embedded, TLS uses rustls, fonts are bundled in Docker)
### Rust Crates
**Backend (`backend/Cargo.toml`):**
| Crate | Version | Purpose |
|-------|---------|---------|
| `axum` | 0.7 | HTTP framework with WebSocket support |
| `tokio` | 1 (full) | Async runtime |
| `reqwest` | 0.12 (rustls-tls, json) | HTTP client for all external API calls |
| `sqlx` | 0.8 (sqlite, migrate) | Async SQLite with compile-time-safe queries |
| `tower-http` | 0.5 (cors, fs) | CORS middleware and static file serving |
| `tower` | 0.4 | Service trait and middleware utilities |
| `tower_governor` | 0.4 | Rate limiting middleware (token bucket) |
| `governor` | 0.6 | Rate limiter backend |
| `genpdf` | 0.2 | PDF report generation |
| `serde` / `serde_json` | 1 | JSON serialization |
| `chrono` | 0.4 | Date/time handling |
| `anyhow` | 1 | Error handling |
| `tracing` / `tracing-subscriber` | 0.1 / 0.3 | Structured logging |
| `dotenvy` | 0.15 | `.env` file loading |
| `futures-util` | 0.3 | `join_all` for parallel async tasks |
| `urlencoding` | 2 | URL encoding for API query parameters |
**Frontend (`frontend/Cargo.toml`):**
| Crate | Version | Purpose |
|-------|---------|---------|
| `yew` | 0.21 (csr) | Component framework compiling to WASM |
| `yew-router` | 0.18 | Client-side routing |
| `wasm-bindgen` | 0.2 | Rust โ JavaScript interop |
| `wasm-bindgen-futures` | 0.4 | Bridge between Rust futures and JS promises |
| `gloo` | 0.11 | Browser API utilities (timers, net, storage) |
| `gloo-net` | 0.6 | HTTP client (fetch API wrapper) |
| `gloo-timers` | 0.3 | setTimeout/setInterval wrappers |
| `web-sys` | 0.3 | Raw DOM API bindings (Window, Navigator, Clipboard, WebSocket, etc.) |
| `js-sys` | 0.3 | JavaScript standard library bindings |
| `serde` / `serde_json` | 1 | JSON serialization |
| `serde-wasm-bindgen` | 0.6 | Efficient serde โ JsValue conversion |
**Shared (`shared/Cargo.toml`):**
| Crate | Version | Purpose |
|-------|---------|---------|
| `serde` | 1 (derive) | Serialization derives for all domain types |
| `serde_json` | 1 | JSON parsing utilities |
### JavaScript (vendored, no npm required)
- **Cytoscape.js** v3.30 โ Graph visualization library for attack path rendering
- **Chart.js** v4.4 โ Charting library for telemetry visualizations
Both are included as minified files in `frontend/static/` and loaded via `` tags in `index.html`.
## Development (without Docker)
### Prerequisites
```bash
# Install Rust (if not already installed)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Add WASM target
rustup target add wasm32-unknown-unknown
# Install Trunk (WASM build tool)
cargo install trunk --locked
```
### Running the Backend
```bash
cp .env.example .env
# Edit .env to add GITHUB_TOKEN and/or NVD_API_KEY if desired
cargo run -p backend
# Serves API on http://localhost:3000
# Also serves frontend from STATIC_DIR if dist/ exists
```
### Running the Frontend (dev mode with hot reload)
```bash
cd frontend
trunk serve
# Serves on http://localhost:8080
# Proxies /api/* and /ws to http://localhost:3000 (configured in Trunk.toml)
```
### Full Workspace Build
```bash
# Type check everything (native target)
cargo check --workspace
# Type check frontend for WASM
cargo check -p frontend --target wasm32-unknown-unknown
# Build frontend WASM bundle
cd frontend && trunk build --release
# Produces dist/ with index.html + WASM + JS + CSS
# Build backend in release mode
cargo build -p backend --release
# Binary at target/release/backend
```
### Running the Built Application
```bash
# After building both:
cd frontend && trunk build --release && cd ..
cargo build -p backend --release
# Run:
STATIC_DIR=frontend/dist ./target/release/backend
# Open http://localhost:3000
```
## Docker
```bash
# Build and run
docker compose up --build
# Run detached
docker compose up -d
# View logs
docker compose logs -f
# Stop
docker compose down
```
The Dockerfile uses a three-stage build:
1. **backend-builder** โ `rust:1.85-bookworm`: compiles the Axum server in release mode
2. **frontend-builder** โ `rust:1.85-bookworm`: installs Trunk, adds wasm32 target, builds the Yew frontend to WASM
3. **runtime** โ `debian:bookworm-slim`: installs `ca-certificates` (for HTTPS to external APIs) and `fonts-liberation` (for PDF generation), copies the backend binary and frontend dist
The final image is ~120MB. Data is persisted to a Docker volume (`app-data`) mounted at `/data`.
## External API Rate Limits
Without tokens, the system operates within the free tiers of all external APIs:
| API | Free Tier | With Token |
|-----|-----------|------------|
| MITRE CVE | No published limit | N/A |
| NVD | 5 requests / 30 seconds | 50 requests / 30 seconds (`NVD_API_KEY`) |
| FIRST.org EPSS | No published limit | N/A |
| GitHub Search | 10 requests / minute | 30 requests / minute (`GITHUB_TOKEN`) |
| GitHub Contents | 60 requests / hour | 5,000 requests / hour (`GITHUB_TOKEN`) |
| GitLab (Exploit-DB fallback) | Unauthenticated access | N/A |
Setting `GITHUB_TOKEN` is recommended for regular use. It is used for PoC repository search, Exploit-DB code search, Nuclei template search, and README fetching โ a single analysis can make 5โ10 GitHub API calls.
## Usage Notes
- All exploit links and PoC content are provided for **defensive research and authorized testing only**.
- The copy-to-clipboard feature on code blocks uses the browser's Clipboard API (`navigator.clipboard.writeText`), which requires HTTPS in production or localhost in development.
- Old cached CVEs (analyzed before the enrichment upgrade) load without errors โ new fields default to empty/None via `#[serde(default)]`. Re-analyzing a CVE will fetch fresh data from all sources.
- The EPSS metric card shows "(FIRST.org)" when using real data and "(estimated)" when falling back to the heuristic. The Threat Score card shows the NVD CVSS score alongside the MITRE score when they differ.