Configuration¶
Configuration splits into server environment variables (secrets, rate limits, translation) and browser localStorage (stack, UI preferences, cached scan).
Server environment¶
Copy .env.example to .env. Keys are read by dotenv on the Express process only.
| Variable | Default | Description |
|---|---|---|
PORT |
3001 |
HTTP listen port |
SCAN_DAYS |
60 |
Feed look-back window |
API_SECRET |
— | Optional shared secret; when set, requires X-Api-Key or Bearer on /api/* except health |
API_SECRET_PREVIOUS |
— | Previous shared secret accepted during rotation (optional; see SECRETS.md) |
VITE_API_KEY |
— | Client build-time key (same as API_SECRET for single-tenant UI) |
NVD_API_KEY |
— | NVD rate limit key (see GET /api/health?detailed=true → feeds.nvd) |
GITHUB_TOKEN |
— | GitHub advisory API — classic PAT with public_repo scope recommended |
OSV_TIMEOUT_MS |
15000 |
OSV query timeout (ms); retries on HTTP 429/503 |
GITHUB_MAX_PAGES |
3 |
Advisory prefetch depth |
TRANSLATE_ENABLED |
true |
Master translation switch |
TRANSLATE_MAX_ITEMS |
50 |
Per-scan translate cap |
TRANSLATE_BATCH_MAX |
40 |
Per /api/translate request |
TRANSLATE_CONCURRENCY |
3 |
Parallel translation workers |
MYMEMORY_EMAIL |
— | MyMemory identity |
LIBRETRANSLATE_URL |
— | Optional LibreTranslate |
OLLAMA_URL |
— | Local Ollama endpoint |
OLLAMA_MODEL |
llama3.2 |
Ollama model |
RATE_LIMIT_SCAN_PER_MIN |
12 |
Max POST /scan requests per IP per minute |
RATE_LIMIT_WATCH_PER_MIN |
120 |
Max POST /watch requests per IP per minute |
RATE_LIMIT_REPORTS_PER_MIN |
10 |
Max POST /reports/generate per IP (+tenant) per minute |
RATE_LIMIT_POLICY_PER_MIN |
60 |
Max POST /policy/evaluate per IP (+tenant) per minute |
SCAN_TIMEOUT_MS |
— | Abort long scan/watch requests (see .env.example) |
Auth, RBAC, and rate limits¶
| Variable | Default | Description |
|---|---|---|
API_SECRET / API_SECRET_FILE |
— | Shared secret; enables auth + RBAC on /api/v1/* |
API_SECRET_PREVIOUS / API_SECRET_PREVIOUS_FILE |
— | Previous secret accepted during zero-downtime rotation |
API_ROLE |
admin |
Role for X-Api-Key / shared-secret Bearer clients: admin, scanner, viewer, auditor |
OIDC_ISSUER |
— | Enable Bearer JWT auth; verify tokens against this issuer |
OIDC_CLIENT_ID |
— | Public SPA client id exposed to the Web UI for SSO login |
OIDC_JWKS_URI |
— | JWKS URL (optional — discovered from issuer when omitted) |
OIDC_AUDIENCE |
— | Optional JWT aud validation |
OIDC_GROUPS_CLAIM |
groups |
Claim path for IdP groups (e.g. realm_access.roles) |
OIDC_ROLE_MAPPING |
— | JSON map IdP group name → API role |
OIDC_DEFAULT_ROLE |
— | Fallback API role when JWT is valid but unmapped |
OIDC_UI_SCOPES |
openid profile email |
OAuth scopes requested by the Web UI SSO button |
RATE_LIMIT_API_PER_MIN |
240 |
General API bucket per IP |
TRUST_PROXY_HOPS |
— | Express trust proxy hops when behind reverse proxy |
AUDIT_HEALTH |
— | Emit structured audit JSON on detailed health probes |
Data, cache, and multi-tenancy¶
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
— | PostgreSQL for scan history, tenants, saved stacks |
DATA_DIR |
./data |
Server data directory (Docker: /app/data) |
REDIS_URL |
— | Shared response cache across instances; also enables BullMQ scan jobs when a worker runs |
JOB_QUEUE_ENABLED |
off | Must be true (with REDIS_URL) to enable BullMQ queue + worker; Redis alone is cache-only |
WORKER_CONCURRENCY |
1 |
Parallel scan jobs per worker process |
JOB_RESULT_TTL_SEC |
3600 |
Redis TTL for completed job result payloads |
CACHE_MAX_ENTRIES |
2000 |
In-memory cache cap when Redis is unset |
Send X-Tenant-Id on /api/v1/* when using Postgres — see Self-hosted tenants.
Air-gap mirrors and Kubernetes¶
| Variable | Description |
|---|---|
AIRGAPPED |
true — use local mirrors only |
NVD_MIRROR_URL / OSV_MIRROR_URL / KEV_MIRROR_URL |
Internal mirror base URLs |
OSV_BULK_PATH |
Extracted OSV bulk JSON directory (alternative to OSV_MIRROR_URL; see make sync-osv-bulk) |
MIRROR_MANIFEST_PATH |
Path to .mirror-manifest.json from npm run mirrors:sync (mirror age metrics) |
MIRROR_STALE_DAYS |
7 |
K8S_DISCOVERY_ENABLED |
Opt-in GET /api/v1/discovery/kubernetes |
K8S_DISCOVERY_NAMESPACES |
Comma-separated namespace list |
K8S_KUBECONFIG |
Path to kubeconfig (in-cluster uses service account when unset) |
Metrics, enrichment, and compliance¶
| Variable | Default | Description |
|---|---|---|
METRICS_ENABLED |
true |
Expose GET /metrics |
METRICS_PROTECT |
false |
Require API_SECRET on /metrics |
EPSS_ENABLED |
true |
FIRST.org EPSS on scan results (disabled when AIRGAPPED=true) |
EPSS_BATCH_SIZE |
100 |
EPSS batch size |
COMPLIANCE_ENABLED |
true |
CWE → NIST/PCI mapping on findings |
NVD_RESULTS_PER_PAGE |
30 |
NVD page size |
NVD_MAX_PAGES |
10 |
NVD pagination cap |
DEEPL_API_KEY / DEEPL_API_KEY_FILE |
— | Preferred translation provider when set |
GitLab and distro feeds¶
| Variable | Default | Description |
|---|---|---|
GITLAB_ADVISORY_ENABLED |
true |
GitLab Advisory Database GraphQL (mirror URL required in air-gap) |
GITLAB_ADVISORY_MIRROR_URL |
— | Internal mirror base for advisories-community |
ALPINE_ENABLED |
true |
Alpine secdb JSON feeds |
ALPINE_RELEASES |
v3.20,v3.21 |
Comma-separated Alpine releases |
ALPINE_SECDB_MIRROR_URL |
— | Internal secdb mirror (air-gap) |
USN_ENABLED |
true |
Ubuntu USN prefetch |
UBUNTU_RELEASES |
jammy,noble |
Ubuntu codenames to filter |
USN_MIRROR_URL |
— | Internal mirror for Ubuntu security JSON |
UBUNTU_CVE_PAGES |
15 |
Pagination depth for Ubuntu CVE pages (× page size below) |
UBUNTU_CVE_PAGE_SIZE |
20 |
Rows per page (Ubuntu API max is 20; higher values return HTTP 422) |
REDHAT_ENABLED |
true |
Red Hat Security Data API enrichment |
REDHAT_SECURITY_API_BASE |
public API | Mirror base for air-gap |
DEBIAN_ENABLED |
false |
Enable Debian Security Tracker HTTP fetch |
DEBIAN_TRACKER_CACHE_PATH |
— | Local tracker JSON directory (air-gap) |
DEBIAN_TRACKER_URL |
tracker.debian.org | Override tracker URL |
ALAS_ENABLED |
true |
Amazon Linux ALAS updateinfo |
ALAS_UPDATEINFO_URL / ALAS_MIRROR_URL |
— | Direct URL or mirror for updateinfo XML |
MITRE_CVE_ENABLED |
false |
MITRE CVE JSON 5.x enrichment pass |
MITRE_CVE_API_BASE |
— | Mirror base for MITRE CVE API |
Server notification environment¶
Optional outbound alerts when watch finds new CVEs (see Alerts). Legacy Slack webhook vars remain supported.
| Variable | Description |
|---|---|
ALERT_WEBHOOK_URL / ALERT_WEBHOOK_URL_FILE |
Legacy Slack-compatible webhook |
ALERT_MIN_SEVERITY |
Minimum severity for legacy webhook |
ALERT_WEBHOOK_FORMAT |
slack or generic JSON |
NOTIFICATION_MIN_SEVERITY |
Global min severity (defaults to ALERT_MIN_SEVERITY or HIGH) |
NOTIFICATION_SLACK_MIN_SEVERITY |
Slack-only override (falls back to global) |
NOTIFICATION_DISCORD_MIN_SEVERITY |
Discord-only override |
NOTIFICATION_TEAMS_MIN_SEVERITY |
Teams-only override |
NOTIFICATION_TELEGRAM_MIN_SEVERITY |
Telegram-only override |
NOTIFICATION_EMAIL_MIN_SEVERITY |
Email-only override |
NOTIFICATION_WEBHOOK_MIN_SEVERITY |
Generic webhook override |
NOTIFICATION_SIEM_MIN_SEVERITY |
SIEM channel override |
NOTIFICATION_DEDUP_MS |
Suppress duplicate posts per channel (default 15 min) |
NOTIFICATION_RATE_LIMIT_PER_HOUR |
Global max successful sends per channel per hour (0 = unlimited) |
NOTIFICATION_SLACK_RATE_LIMIT_PER_HOUR |
Slack hourly cap (falls back to global) |
NOTIFICATION_DISCORD_RATE_LIMIT_PER_HOUR |
Discord hourly cap |
NOTIFICATION_TEAMS_RATE_LIMIT_PER_HOUR |
Teams hourly cap |
NOTIFICATION_TELEGRAM_RATE_LIMIT_PER_HOUR |
Telegram hourly cap |
NOTIFICATION_EMAIL_RATE_LIMIT_PER_HOUR |
Email hourly cap |
NOTIFICATION_WEBHOOK_RATE_LIMIT_PER_HOUR |
Generic webhook hourly cap |
NOTIFICATION_SIEM_RATE_LIMIT_PER_HOUR |
SIEM hourly cap |
NOTIFICATION_SLACK_WEBHOOK_URL |
Dedicated Slack webhook |
NOTIFICATION_DISCORD_WEBHOOK_URL |
Discord webhook URL |
NOTIFICATION_TEAMS_WEBHOOK_URL |
Microsoft Teams Incoming Webhook (MessageCard) |
NOTIFICATION_TELEGRAM_BOT_TOKEN |
Telegram bot token |
NOTIFICATION_TELEGRAM_CHAT_ID |
Telegram chat id |
NOTIFICATION_WEBHOOK_URL |
Generic JSON webhook (Teams-compatible envelope) |
SIEM_WEBHOOK_URL / SIEM_FORMAT |
SIEM ingest webhook; json (default) or cef |
JIRA_BASE_URL / JIRA_EMAIL / JIRA_API_TOKEN / JIRA_PROJECT_KEY |
Jira CRITICAL+KEV tickets on watch |
SERVICENOW_INSTANCE_URL / SERVICENOW_USER / SERVICENOW_PASSWORD |
ServiceNow CRITICAL+KEV incidents |
OPA_URL / OPA_POLICY_PATH / OPA_ENFORCE |
OPA sidecar URL, package path, enforce gate on watch |
ITSM_DEDUP_TTL_MS |
Ticket dedup TTL (default 7 days) |
NOTIFICATION_SMTP_HOST |
SMTP host for email alerts |
NOTIFICATION_SMTP_PORT |
SMTP port (default 587) |
NOTIFICATION_SMTP_USER / NOTIFICATION_SMTP_PASS |
SMTP auth (optional); *_FILE mounts supported for user/pass |
NOTIFICATION_SMTP_FROM / NOTIFICATION_SMTP_TO |
Email sender and recipient |
Client localStorage¶
| Key | Purpose |
|---|---|
cve-radar:stack |
Monitored tool names |
cve-radar:settings |
Alerts, watch, translate, intervals |
cve-radar:setup-complete |
First-run wizard finished (v1.1.0+) |
cve-radar:theme |
light / dark / system |
cve-radar:locale |
UI language code |
cve-radar:font-scale |
85–140 text scale |
cve-radar:sidebar-collapsed |
SubNav narrow mode |
cve-radar:last-scan |
Cached vulns + summary (scanCache.ts, stack-keyed) |
cve-radar:known-ids |
CVE ids for watch deduplication |
cve-radar:sources-updated-at |
Per-source timestamps |
cve-radar:source-config |
Built-in and custom feed toggles |
Never commit .env with real tokens.
API discovery URLs¶
When the server is running, integrators can read limits and contracts without scanning:
| URL | Purpose |
|---|---|
GET /api/health |
Liveness and env flags |
GET /api/capabilities |
Numeric limits and feature flags |
GET /api/sources |
Built-in feed catalog |
GET /api/openapi.json |
OpenAPI 3.1 document |
Versioned equivalents: /api/v1/health, etc. See API reference.
Next: Architecture