Skip to content

Exploitation self-host

Les équipes qui exécutent CVE Radar sur des serveurs internes, Kubernetes ou Docker ont besoin de capacités production dans la même base MIT : journaux audit JSON, montage de secrets, RBAC, multi-tenant PostgreSQL, métriques Prometheus, miroirs airgap et découverte de stack Kubernetes.

Pas de niveau enterprise ni de verrou licence. Les variables d'environnement ne modifient que le comportement opérationnel. Dépannage : Exploitation ; env de base : Configuration.

flowchart TB
  classDef ui fill:#e9edf5,stroke:#00baba,color:#253343
  classDef api fill:#f3fcfc,stroke:#008c8c,color:#253343
  classDef data fill:#fff7ed,stroke:#eda232,color:#253343
  classDef ext fill:#f5f5f5,stroke:#666,color:#253343

  subgraph deploy["Déploiement self-host"]
    Browser[SPA navigateur]:::ui
    API[Express API]:::api
    PG[(PostgreSQL optionnel)]:::data
    Metrics["GET /metrics"]:::api
    Audit[stdout audit JSON]:::ext
  end

  Browser --> API
  API --> PG
  API --> Metrics
  API --> Audit
  API --> Feeds[NVD / OSV / miroirs]:::ext
  API --> Notify[Slack / SMTP / webhooks]:::ext

Le schéma montre Postgres optionnel, scrape Prometheus sur /metrics, audit stdout et notifications après watch. En airgap, les feeds publics sont remplacés par des miroirs locaux (voir Déploiement airgap).

Journaux audit

CVE Radar peut émettre une ligne JSON par événement audit sur stdout pour ELK, Loki, Splunk ou le driver Docker json-file.

action Quand
scan Après chaque POST /api/scan
watch Après chaque POST /api/watch
health Si AUDIT_HEALTH=true et health détaillé
export Pas encore côté serveur (export navigateur)
{
  "audit": true,
  "ts": "2026-06-06T14:30:00.000Z",
  "action": "scan",
  "ip": "10.0.0.42",
  "stack": ["redis", "nginx"],
  "duration_ms": 8420,
  "sources_failed": ["NVD"],
  "result_count": 12,
  "mode": "full"
}

Réglez TRUST_PROXY_HOPS derrière un reverse proxy. Titres CVE et clés API jamais journalisés.

docker logs cve-radar 2>&1 | grep '"audit":true'

Secrets et production

env direct env fichier (*_FILE)
NVD_API_KEY NVD_API_KEY_FILE
GITHUB_TOKEN GITHUB_TOKEN_FILE
DEEPL_API_KEY DEEPL_API_KEY_FILE
ALERT_WEBHOOK_URL ALERT_WEBHOOK_URL_FILE
NOTIFICATION_SLACK_WEBHOOK_URL
NOTIFICATION_DISCORD_WEBHOOK_URL
NOTIFICATION_TELEGRAM_BOT_TOKEN
NOTIFICATION_SMTP_PASS mount via env file Compose
API_SECRET API_SECRET_FILE

Exemple : docker-compose.secrets.example.yml. Sur Kubernetes, montez un Secret en fichiers.

RBAC et authentification API

Avec API_SECRET, toutes les routes /api/* sauf GET /api/health et GET /api/v1/health exigent X-Api-Key ou Bearer. API_ROLE :

Rôle Permissions
admin Réglages, CRUD stacks tenant, scan/watch, translate, meta et history
scanner scan/watch/validate, translate, meta et history
viewer meta et history — pas de scan
auditor history/trends et meta — pas de scan

Par défaut admin. Un viewer sur POST /api/scan reçoit 403 { "code": "FORBIDDEN" }.

Notifications watch

Les opérateurs self-host ont souvent besoin d'alertes hors bande quand le watch planifié détecte de nouveaux CVE. CVE Radar envoie les notifications serveur de façon asynchrone après POST /api/watch avec newVulns non vide — la réponse HTTP est inchangée.

Canal env principales
Slack NOTIFICATION_SLACK_WEBHOOK_URL ou legacy ALERT_WEBHOOK_URL
Discord NOTIFICATION_DISCORD_WEBHOOK_URL
Telegram NOTIFICATION_TELEGRAM_BOT_TOKEN, NOTIFICATION_TELEGRAM_CHAT_ID
E-mail SMTP NOTIFICATION_SMTP_HOST, FROM, TO ; optionnel PORT, USER, PASS
Webhook générique NOTIFICATION_WEBHOOK_URL
Contrôle env Défaut
Sévérité min. NOTIFICATION_MIN_SEVERITY / ALERT_MIN_SEVERITY HIGH
Fenêtre dedup (ms) NOTIFICATION_DEDUP_MS 900000
Format Slack ALERT_WEBHOOK_FORMAT slack / generic

Le webhook Slack legacy (ALERT_WEBHOOK_URL) fonctionne via NotificationService. NOTIFICATION_* accepte les mounts *_FILE. Vérifiez : GET /api/health?detailed=truealerts.webhookConfigured. Voir Alertes et NOTIFICATIONS.md.

Multi-tenant (PostgreSQL)

DATABASE_URL=postgres://cve_radar:cve_radar@127.0.0.1:5432/cve_radar

Les migrations s'exécutent au premier pool. Schéma dans server/db/schema.ts (Drizzle ORM) pour migration ORM progressive ; les requêtes runtime tenant/stack et scan-history passent par Drizzle via getDb() (pool pg partagé).

X-Tenant-Id: arvancloud-sre
Method Path Description
POST /api/v1/tenants Créer tenant
GET /api/v1/tenants/stacks Lister stacks
POST /api/v1/tenants/stacks Créer stack
GET /api/v1/tenants/stacks/:id Stack par UUID
PUT /api/v1/tenants/stacks/:id Mettre à jour
DELETE /api/v1/tenants/stacks/:id Supprimer
GET /api/v1/scans/history History tenant
GET /api/v1/scans/trends Trends tenant

History filtrée par tenant_id. Routes legacy /api/* sous tenant default.

Prometheus et Grafana

GET /metrics. METRICS_ENABLED (true par défaut), METRICS_PROTECT pour auth.

Métrique Type Description
cve_radar_scans_total counter scan/watch
cve_radar_vulns_found gauge dernier scan réussi
cve_radar_scan_duration_seconds histogram durée handler
cve_radar_source_reachable gauge upstream
cve_radar_cache_entries_total gauge taille cache

Dashboard : docs/self-hosted/grafana/cve-radar-dashboard.json.

sum(rate(cve_radar_scans_total{status="success"}[5m]))
  / sum(rate(cve_radar_scans_total[5m]))

Déploiement airgap

AIRGAPPED=true
NVD_MIRROR_URL=http://internal-mirror/nvd
KEV_MIRROR_URL=http://internal-mirror/kev/catalog.json
# OSV — mirror ou bulk :
OSV_MIRROR_URL=http://internal-mirror/osv
# OSV_BULK_PATH=/data/osv/extracted

Avec OSV_BULK_PATH, OSV lit l’arborescence JSON locale (scripts/sync-osv-bulk.sh / make sync-osv-bulk) sans API query. GitHub, RSS et traduction externe ignorés. Mirror NVD/KEV manquant → fail-closed. jq .airgap sur health détaillé. scripts/sync-mirrors.sh, scripts/sync-osv-bulk.sh.

Découverte Kubernetes

K8S_DISCOVERY_ENABLED=true
# K8S_DISCOVERY_NAMESPACES=production,staging

GET /api/v1/discovery/kubernetes — auth requise en production. Désactivé → 503 K8S_DISCOVERY_DISABLED.

{
  "enabled": true,
  "images": ["haproxy", "nginx", "redis"],
  "tools": ["HAProxy", "Nginx", "Redis"],
  "unmapped": ["my-sidecar"]
}

ServiceAccount lecture seule sur deployments. Combiner avec isolation tenant.

Référence rapide

Sujet env
Audit AUDIT_HEALTH, TRUST_PROXY_HOPS
Secrets mount *_FILE
RBAC API_SECRET, API_ROLE
Notifications NOTIFICATION_*, ALERT_WEBHOOK_URL
Tenant DATABASE_URL, X-Tenant-Id
Métriques METRICS_ENABLED, METRICS_PROTECT
Airgap AIRGAPPED, *_MIRROR_URL, OSV_BULK_PATH
K8s K8S_DISCOVERY_ENABLED, K8S_DISCOVERY_NAMESPACES
Enrichment EPSS_ENABLED, COMPLIANCE_ENABLED

Copies maintainer : docs/self-hosted/.

Accueil · Précédent : Exploitation