Share
## https://sploitus.com/exploit?id=C4C43757-15B5-5D3E-B518-F825D7611271
# VulnForge

Local-only, single-user CVE alert & patch-priority dashboard. Paste a CVE ID, get NVD/EPSS/KEV enrichment, an Ease-of-Exploitation score, an LLM-generated diff-to-exploit assessment, Akamai WAF rule suggestions, and a chat assistant scoped to that CVE.

See [`CVE-Dashboard-Product-Plan.md`](./CVE-Dashboard-Product-Plan.md) for the full design.

## Quick start

Prereqs: Python 3.11+, Node 20+, [`uv`](https://docs.astral.sh/uv/) (`brew install uv`), `pnpm` (`brew install pnpm`).

```sh
./dev.sh
```

This boots:
- Backend on http://localhost:8000 (FastAPI + SQLite)
- Frontend on http://localhost:5173 (Vite + React)

Open the frontend, go to **Settings**, and paste your API keys (Anthropic at minimum โ€” everything else is optional). Then paste a CVE ID into the search bar.

## Architecture

- **Backend:** FastAPI, SQLite + FTS5, async via `httpx`. No Docker, no Celery, no Redis.
- **Frontend:** Vite + React 19 + TypeScript + Tailwind v4 + shadcn/ui.
- **LLM:** Claude API (Sonnet 4.6 default, Opus 4.7 for deep analysis). Prompt caching enabled.
- **Plugins:** Drop a `.py` file in `backend/app/plugins/sources/` to add a new enrichment source. The Settings UI auto-renders required-key inputs.
- **Secrets:** Stored encrypted (AES-GCM) in SQLite; master key at `~/.vulnforge/master.key`. No keys in `.env`.

## Project layout

```
backend/
  app/
    api/routes/        FastAPI route modules
    models/            SQLAlchemy ORM models
    plugins/
      sources/         Enrichment source plugins (auto-discovered)
      llm/             LLM provider plugins
    services/          Domain services (enrichment, scoring, briefing, chat)
  alembic/             DB migrations
  tests/
frontend/
  src/
    api/               Backend client
    components/        Reusable UI
    pages/             Route components
    hooks/
    lib/
    types/
```

## Adding a new enrichment source

Create `backend/app/plugins/sources/yoursource.py`:

```python
from app.plugins.base import EnrichmentSource, SourceContext

class YourSource(EnrichmentSource):
    name = "yoursource"
    display_name = "Your Source"
    required_secrets = ["yoursource_api_key"]
    produces = ["yoursource_field"]

    async def enrich(self, cve, ctx: SourceContext) -> dict:
        key = ctx.secrets.get("yoursource_api_key")
        # ... call API, return enriched fields
        return {"yoursource_field": "..."}
```

Restart the backend. The Settings UI will show your plugin with an input field for `yoursource_api_key`. Paste your key, hit Save, and the next CVE lookup will include your data.