Skip to content

Latest commit

History

12 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Warden

Open-source vulnerability management orchestratorCaptura de pantalla 2026-03-17 a la(s) 7 26 30 p m

Aggregate findings from every scanner you run, deduplicate across sources, enrich with real-world threat context, and surface a single prioritized list — so your team remediates what matters most, not just what scanned last.

License: MITPython 3.11+FastAPIReact 18Docker


Why Warden?

Most organizations run 3–5 vulnerability scanners. Each one produces its own findings list, its own severity ratings, its own duplicates. Triaging that noise manually doesn't scale.

Warden connects to your existing scanners, merges their output into one deduplicated view, and scores each finding using six signals — CVSS, CISA KEV status, EPSS, SSVC decision, exploit availability, and asset criticality — so your security team has a clear, defensible answer to "fix this first." Captura de pantalla 2026-03-17 a la(s) 7 26 03 p m


What it does

CapabilityDetail
Multi-scanner ingestionNessus, Tenable.io, Qualys VMDR, Rapid7 InsightVM, Microsoft Defender, CrowdStrike Falcon
AppSec connectorsSAST (Semgrep / Bandit), SARIF (CodeQL, Checkmarx, ESLint Security…), SCA (pip-audit / npm audit), DAST (OWASP ZAP / Burp Suite / Nuclei), Containers & IaC (Trivy)
DeduplicationOne finding per CVE/asset pair, regardless of how many scanners reported it
Threat enrichmentCISA KEV catalog (auto-synced daily), EPSS scores, NVD metadata, GreyNoise CVE intelligence (internet-wide scanning activity)
SSVC prioritizationCISA decision tree: Exploitation × Automatable × Technical Impact → Immediate / Act / Attend / Track
Risk scoringConfigurable 6-factor model (see Risk model below)
SLA trackingConfigurable deadlines per severity with overdue alerting
Ticketing & alertsJira auto-ticket creation · Slack KEV alerts
ExportCSV endpoint compatible with Tableau and Power BI (templates included)
REST APIFull API with Swagger UI — integrate with any SOAR or workflow

Quick start

Requires Docker and Docker Compose.

git clone https://github.com/stv3/warden.git
cd warden
# 1. Configure environment
cp .env.example .env

Open .env and set four values before starting:

VariableWhat to set
WARDEN_SECRET_KEYRun python3 -c "import secrets; print(secrets.token_hex(32))" and paste the output
AUTH_PASSWORDAny strong password — this is your login password
POSTGRES_PASSWORDAny strong password for the database

DATABASE_URL is assembled automatically from POSTGRES_PASSWORD — you don't need to touch it.

# 2. Build and start (first run takes ~3 min to build the frontend)
docker compose up -d --build
# 3. Open the dashboard# http://localhost# Login: admin / <AUTH_PASSWORD you set in step 1>

Postgres and Redis are included in the compose file — no external dependencies.

Port 80 already in use? Set WARDEN_HTTP_PORT=8080 (or any free port) in .env, then restart. Access Warden at http://localhost:8080. CORS is auto-configured — no extra steps needed.

HTTPS (self-signed, for private/internal networks)

# 1. Generate a self-signed certificate
./scripts/generate-selfsigned-cert.sh # defaults to localhost
./scripts/generate-selfsigned-cert.sh 192.168.1.50 # or a specific IP/hostname# 2. Build and start with HTTPS (must include the selfsigned overlay)
docker compose -f docker-compose.yml -f docker-compose.selfsigned.yml up -d --build
# Dashboard at https://localhost (accept the browser warning for self-signed certs)

The first run builds the frontend image (~3 min). Subsequent starts are instant.

For internet-accessible deployments with a real domain, use docker-compose.https.yml + init-letsencrypt.sh (Let's Encrypt).


Dashboard

The React dashboard ships built-in — no separate BI tool required.

Findings — filter by severity, scanner, SSVC decision, exploit availability, owner, and date range. Drill into any finding for full NVD details, CWE classification, and remediation context.

Risk metrics — SSVC distribution, exploit availability breakdown, top CWEs by exposure, attack vector analysis, SLA compliance trends, and mean time to remediate.

Pipeline — trigger scanner ingestion, monitor job status, and view enrichment results in real time.

Screenshots: run the demo seed script (docker compose exec api python scripts/seed_demo_data.py) to populate 60 realistic findings and see the full dashboard.


Risk model

Warden scores each finding on a 0–100 scale using six factors:

SignalWeightSource
CVSS base score20%Scanner / NVD
CISA KEV status25%CISA KEV catalog (daily sync)
Asset criticality15%Configured per asset (1–5)
SSVC decision15%Derived from KEV + EPSS + CVSS vector
EPSS score10%FIRST.org daily feed
Public exploit available10%NVD reference tags

SSVC decisions map to remediation urgency:

DecisionMeaningSLA
ImmediateActive exploitation + automatable + total impactCritical SLA
ActActive exploitation or high-probability PoCHigh priority
AttendPoC available or partially automatableStandard SLA
TrackNo known exploitation pathNormal backlog

Tune the weights for your environment in config/risk_model.yaml.


Configuration

All settings are environment variables. Copy .env.example to .env to get started.

Required:

VariableDescription
WARDEN_SECRET_KEYJWT signing key — generate with secrets.token_hex(32)
AUTH_PASSWORDDashboard login password
POSTGRES_PASSWORDDatabase password — DATABASE_URL is auto-assembled from this
WARDEN_ENVdevelopment (warnings only) or production (blocks insecure defaults at startup)

Port configuration:

VariableDefaultDescription
WARDEN_HTTP_PORT80Host port for the HTTP UI — change if 80 is already in use
WARDEN_HTTPS_PORT443Host port for HTTPS (selfsigned/Let's Encrypt overlay)
CORS_ORIGINSautoComputed from the port vars above — only override for non-localhost deployments

Scanner credentials (configure only what you use):

Variable(s)Scanner
NESSUS_URL, NESSUS_USERNAME, NESSUS_PASSWORDNessus (self-hosted)
TENABLE_ACCESS_KEY, TENABLE_SECRET_KEYTenable.io
QUALYS_API_URL, QUALYS_USERNAME, QUALYS_PASSWORDQualys VMDR
RAPID7_URL, RAPID7_API_KEY, RAPID7_SITE_IDRapid7 InsightVM
DEFENDER_TENANT_ID, DEFENDER_CLIENT_ID, DEFENDER_CLIENT_SECRETMicrosoft Defender
CROWDSTRIKE_CLIENT_ID, CROWDSTRIKE_CLIENT_SECRETCrowdStrike Falcon
JIRA_URL, JIRA_USERNAME, JIRA_API_TOKEN, JIRA_PROJECT_KEYJira ticketing
SLACK_WEBHOOK_URLSlack KEV alerts
NVD_API_KEYNVD API (optional — increases rate limit from 5 to 50 req/30s)

Architecture

┌─────────────────────────────────────────────────────────────────┐
│ React Dashboard │
│ (Vite + TypeScript + Tailwind CSS) │
└────────────────────────────┬────────────────────────────────────┘
│ REST / JSON
┌────────────────────────────▼────────────────────────────────────┐
│ FastAPI (Python 3.11) │
│ /api/findings /api/metrics /api/pipeline /api/export │
└──────────┬──────────────────────────────────────────┬───────────┘
│ │
┌──────────▼──────────┐ ┌──────────▼──────────┐
│ PostgreSQL │ │ Celery Workers │
│ (findings, KEV) │ │ (pipeline, alerts) │
└─────────────────────┘ └──────────┬──────────┘
│
┌──────────▼──────────┐
│ Redis │
│ (task queue) │
└─────────────────────┘
Connectors: Nessus · Tenable.io · Qualys · Rapid7 · Defender · CrowdStrike
Semgrep / Bandit (SAST) · SARIF (CodeQL, Checkmarx…) · pip-audit (SCA)
OWASP ZAP / Burp Suite / Nuclei (DAST) · Trivy (containers/IaC)
Feeds: CISA KEV catalog · EPSS (FIRST.org) · NVD API · GreyNoise
Integrations: Jira · Slack

API

The full API is documented at http://localhost:8000/docs (Swagger UI). To enable in production set WARDEN_DOCS_ENABLED=true in .env.

Key endpoints:

MethodPathDescription
POST/auth/tokenGet a JWT token
GET/api/findings/List findings (filter by severity, CVE, SSVC, owner…)
PATCH/api/findings/{id}/statusUpdate status or owner
GET/api/metrics/kev-exposureKEV exposure summary
GET/api/metrics/ssvc-distributionSSVC decision breakdown
GET/api/metrics/exploit-statsExploit availability stats
GET/api/metrics/sla-complianceSLA compliance by severity
GET/api/metrics/mttrMean time to remediate
POST/api/pipeline/runTrigger ingestion pipeline
GET/api/export/tableau/findings.csvFull findings export

All endpoints require Authorization: Bearer <token>.


Try it with demo data

No scanner credentials? Populate 60 realistic findings (Log4Shell, MOVEit, PAN-OS, and others) to explore the full dashboard:

docker compose exec api python scripts/seed_demo_data.py

Local development

Requires Python 3.11+, Node 18+, PostgreSQL, and Redis.

# Backend
python3 -m venv .venv &&source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # fill in values
uvicorn api.main:app --reload --port 8000
# Frontend (separate terminal)cd frontend && npm install && npm run dev
# Vite dev server at http://localhost:5173 — proxies /api, /auth, /health to :8000

Running tests

pip install -r requirements.txt
pytest # all tests
pytest tests/ -v # verbose

Tests use SQLite in-memory — no Postgres or Redis required.


Adding a connector

Inherit from connectors.base.BaseConnector and implement fetch_findings(). The pipeline picks it up automatically. See any existing connector in connectors/ as a reference.


BI templates

Tableau and Power BI templates are in templates/:

  • warden_executive_dashboard.twb — Tableau workbook with 8 worksheets (Executive Overview + Asset & Operations dashboards)
  • warden_powerbi_setup.md — Power BI setup guide with Power Query M script, DAX measures, and recommended layout

Security

  • HTTPS — self-signed cert generator included; Let's Encrypt overlay for public deployments
  • Authentication — JWT with configurable expiry and brute-force rate limiting
  • Startup checks — Warden refuses to start in production with default or weak credentials
  • CORS — explicit origin allowlist (no wildcards)
  • Input validation — CVE IDs and owner fields validated on all write endpoints
  • Headers — HSTS, CSP, X-Frame-Options, X-Content-Type-Options set by nginx

To report a vulnerability, open a GitHub issue marked [security] or contact the maintainers directly.


Troubleshooting

API exits with password authentication failed for user "vuln" The Postgres volume was initialized with a different password than what's in .env now. Wipe it and restart:

docker compose down -v # -v removes the postgres volume
docker compose up -d --build

docker compose up exits immediately / API won't start Check that .env exists and WARDEN_SECRET_KEY, AUTH_PASSWORD, and POSTGRES_PASSWORD are all set. If WARDEN_ENV=production, Warden blocks startup with weak or default credentials — set strong values or switch to WARDEN_ENV=development for local testing.

Dashboard shows a blank page or 403 The frontend image needs to be built first. Run docker compose up -d --build — Docker builds the React app during the first start (takes ~3 minutes). Subsequent starts are instant.

Port 80 is already in use (bind: address already in use) Another service (nginx, Apache, another Docker container) is using port 80. Set WARDEN_HTTP_PORT=8080 (or any free port) in .env, then:

docker compose up -d --build
# Access Warden at http://localhost:8080

CORS is auto-computed from the port — no other changes needed.

Login says "Invalid credentials" Check that you're using the password you set in .env as AUTH_PASSWORD. The username is always admin (or whatever AUTH_USERNAME is set to). If you never edited AUTH_PASSWORD, the value is change-me-use-a-strong-password from the example file — update it and restart: docker compose restart api.

If the error message says "Cannot reach the API", the issue is CORS or the API container is down — see the next two entries.

Browser shows "connection refused" or "Cannot reach the API" Run docker compose ps — the API container may have exited. Check docker compose logs api for the error. Common causes: missing .env, wrong DATABASE_URL hostname (must be db, not localhost), or POSTGRES_PASSWORD not set.

After restarting the API, login stops working (502) Restarting the API assigns it a new internal IP. nginx caches the old one. Fix: docker compose restart ui immediately after docker compose restart api.

HTTPS returns 502 or connection refused Plain docker compose up only binds port 80 — HTTPS requires the selfsigned overlay:

./scripts/generate-selfsigned-cert.sh # only needed once
docker compose -f docker-compose.yml -f docker-compose.selfsigned.yml up -d --build
# Dashboard at https://localhost

Self-signed certificate browser warning This is expected — you need to trust the cert once. See the output of ./scripts/generate-selfsigned-cert.sh for OS-specific trust commands (macOS Keychain / Linux update-ca-certificates).

Celery worker not processing jobs Run docker compose logs worker — if you see Redis connection errors, confirm REDIS_URL=redis://redis:6379/0 (not localhost) in your .env.

psycopg2.errors.UndefinedColumn on new columns after upgrading Warden doesn't use Alembic migrations. After pulling new code that adds model columns, run the ALTER TABLE statements from the commit message against your database:

docker compose exec db psql -U vuln vuln_orchestrator

NVD enrichment is slow Get a free NVD API key at https://nvd.nist.gov/developers/request-an-api-key and set NVD_API_KEY= in .env. It raises the rate limit from 5 to 50 requests per 30 seconds.


Contributing

Pull requests are welcome. See CONTRIBUTING.md for guidelines.


License

MIT

About

Open-source vulnerability management orchestrator — aggregate, deduplicate, and prioritize findings from every scanner using CVSS, KEV, EPSS, SSVC, and exploit availability

Topics

Resources

Contributing

Security policy

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages