Référence HTTP API¶
CVE Intelligence Panel expose une API REST JSON sans état sur le serveur Node/Express. L’UI utilise les mêmes endpoints via le proxy Vite en développement (/api → localhost:3001) et des chemins same-origin en production. Les intégrateurs peuvent appeler l’API depuis des scripts, des portes CI ou des tableaux de bord internes sans charger le client React.
Ce chapitre décrit chaque route publique, la validation des requêtes, les formes de réponse, les codes d’erreur et les limites opérationnelles. Pour des essais interactifs sans serveur actif, utilisez l’onglet API Explorer (mock navigateur). Pour les contrats lisibles par machine, appelez GET /api/openapi.json.
Principes de conception de l’API¶
L’API suit les conventions courantes : corps JSON, UTF-8, pas de cookies de session (adaptée aux reverse proxy et API gateway), et modes de scan explicites (full vs watch) reflétés dans meta.mode. Chaque scan est indépendant ; le serveur ne persiste ni votre stack ni les résultats sauf si vous stockez les réponses côté client.
Deux préfixes d’URL sont pris en charge :
| Préfixe | Rôle |
|---|---|
/api/* |
Chemins compatibles avec l’UI livrée |
/api/v1/* |
Surface versionnée (mêmes handlers, stable pour l’intégration) |
Les nouvelles intégrations devraient préférer /api/v1 et traiter /api comme alias pendant la transition.
Découverte et métadonnées¶
Avant un scan, les clients appellent généralement les endpoints de découverte pour connaître les limites, les sources disponibles et la configuration runtime.
Santé — GET /api/health (aussi /api/v1/health)¶
Retourne la liveness plus des indicateurs non secrets. À utiliser pour les health checks de load balancer et les sondes de démarrage.
Champs de réponse (résumé) :
| Champ | Signification |
|---|---|
ok |
Toujours true lorsque le processus tourne |
version |
Semver de l’app depuis package.json (ex. 1.1.0) |
sources |
IDs des flux intégrés |
nvdApiKey / githubToken |
Si les identifiants env sont définis (pas les valeurs) |
scanDays |
Fenêtre look-back depuis SCAN_DAYS (défaut 60) |
translate |
Si la traduction côté serveur est autorisée |
limits |
Plafonds numériques (taille stack, tailles de batch) |
Detailed probe: GET /api/health?detailed=true — uptime, reachability par source, cache, air-gap, alerts.webhookConfigured (toute chaîne de notification), alerts.minSeverity.
Prometheus metrics — GET /metrics¶
Chemin racine (hors /api). METRICS_ENABLED=true par défaut ; METRICS_PROTECT=true exige API_SECRET. Voir Self-hosted metrics.
Capabilities — GET /api/capabilities¶
Retourne les limites produit et feature flags structurés (max outils par scan, locales de traduction, modes de scan). Préférez ceci à l’analyse de health pour construire des formulaires ou validateurs CI.
Catalogue des sources — GET /api/sources¶
Retourne le registre des sources intégrées (NVD, OSV, GitHub, CISA KEV, flux RSS) avec kind, fullScan, watchScan, plus les URL RSS par défaut. Les flux personnalisés ne sont pas listés ici ; les clients les fournissent par requête via customFeeds.
OpenAPI — GET /api/openapi.json¶
Sert le document OpenAPI 3.1 (server/openapi/spec.json) pour codegen, import Postman ou tests de contrat.
Validation des requêtes et erreurs¶
Tous les corps POST doivent être des objets JSON. Les échecs de validation renvoient HTTP 400 :
{
"error": "Human-readable message",
"code": "VALIDATION_ERROR",
"details": { "max": 50, "received": 72 }
}
Les échecs upstream (rate limit NVD, timeout RSS) renvoient 502 ou 429 avec texte error et code optionnel (SCAN_FAILED, WATCH_FAILED). L’UI affiche error comme chaîne ; les intégrateurs peuvent aussi lire code et details.
Limite de débit applicative (middleware) : lorsqu’un client dépasse les quotas scan ou veille par IP, le serveur renvoie HTTP 429 :
{
"error": "Too many scan requests. Try again later.",
"code": "RATE_LIMITED",
"retryAfterSec": 42
}
POST /scanetPOST /watchutilisent des buckets séparés par minute.POST /scan/validateest exempt (sûr pour CI et vérification de pile).- Régler via
RATE_LIMIT_SCAN_PER_MINetRATE_LIMIT_WATCH_PER_MINdans.env.
API key / RBAC (v1): avec API_SECRET, routes protégées + rôles sur /api/v1/* (API_ROLE, 403 si rôle insuffisant). En-tête X-Tenant-Id avec PostgreSQL.
Règles de stack :
stack— tableau obligatoire non vide de noms d’outils (trim), max 50 outils.customFeeds— optionnel, max 20 entrées ; chaque entrée requiertideturl.enabledBuiltin— carte optionnelle source ID → boolean ; clés absentes activées par défaut.
Validation sans scan — POST /api/scan/validate¶
Valide stack, enabledBuiltin et customFeeds sans appeler les fournisseurs CVE externes. À utiliser dans les assistants ou CI pour rejeter une entrée invalide avant un full scan coûteux.
Exemple de requête :
{
"stack": ["Redis", "HAProxy"],
"enabledBuiltin": { "NVD": true, "TuxCare": false },
"customFeeds": [{ "id": "custom:team-feed", "name": "Team RSS", "url": "https://example.com/cve.rss" }]
}
Exemple de réponse :
{
"valid": true,
"stack": ["Redis", "HAProxy"],
"toolCount": 2,
"customFeedCount": 1,
"message": "Stack and source options are valid; run POST /api/scan for findings."
}
Scan complet — POST /api/scan¶
Exécute un scan complet : NVD, OSV, GitHub Advisories, CISA KEV, RSS intégrés et flux RSS personnalisés activés. Les résultats sont fusionnés par ID CVE, enrichis des flags KEV, traduits optionnellement, puis renvoyés en une seule charge.
Corps de requête :
| Champ | Type | Requis | Description |
|---|---|---|---|
stack |
string[] |
oui | Noms d’outils à matcher |
translate |
boolean |
non | Si true, traduire titres/descriptions |
locale |
fa | ar | ru | zh | fr |
non | Langue cible si translate: true |
enabledBuiltin |
object |
non | Bascules par source |
customFeeds |
array |
non | Flux RSS/Atom supplémentaires (IDs custom:…) |
Exemple :
{
"stack": ["Redis", "HAProxy", "Kubernetes"],
"translate": true,
"locale": "fr",
"enabledBuiltin": { "NVD": true, "TheHackerNews": true }
}
Réponse : ScanResponse — vulns[], summary, search_date, meta (sources_checked, sources_updated_at, duration_ms, mode: "full").
Chaque vulnérabilité inclut id, tool, title, severity, optionnellement affected_versions, fixed_version, sources[], url, patch_available, exploited_in_wild, optionnellement epss (0–1) et riskScore (0–10) si EPSS est activé, cwe[] et compliance_controls[] si la conformité est activée, et translations / title_fa si enrichi.
Séquence de scan (vue intégrateur)¶
sequenceDiagram
participant Client
participant API as Express API
participant Feeds as Flux externes
Client->>API: POST /api/scan { stack, translate, locale }
API->>Feeds: NVD/OSV/GitHub/KEV/RSS en parallèle
Feeds-->>API: Résultats bruts
API->>API: Fusion, enrichissement KEV, traduction opt.
API-->>Client: 200 { vulns, summary, meta }
Description du diagramme¶
Le client envoie une charge JSON unique. Le serveur distribue vers les sources configurées, normalise les enregistrements en forme de vulnérabilité commune, déduplique par ID CVE et applique une traduction optionnelle sur les N premiers éléments (contrôlé par TRANSLATE_MAX_ITEMS). La réponse inclut des métadonnées de timing pour afficher la progression ou auditer les SLA.
Déroulement pas à pas¶
- Appelez
GET /api/capabilitiespour liremaxStackToolsettranslateLocales. - Optionnellement
POST /api/scan/validateavec le même corps que le scan prévu. POST /api/scanavecstacket options de sources.- Stockez
vulnsetmeta.sources_updated_atsi vous avez besoin de badges UI incrémentaux. - Sur 429, augmentez le backoff et réduisez la fréquence des scans lourds en NVD.
Watch — POST /api/watch¶
Exécute le mode watch : OSV, GitHub, KEV et RSS sans NVD pour une latence moindre. Le corps correspond au scan plus knownIds optionnel (IDs CVE déjà vus). La réponse ajoute newVulns et hasNew pour les pipelines d’alerte.
Exemple :
{
"stack": ["Redis"],
"knownIds": ["CVE-2024-1234", "CVE-2023-9999"],
"translate": false
}
Réponse : comme scan plus newVulns[], hasNew: boolean, meta.mode: "watch".
Lorsque newVulns est non vide et que les variables de notification sont définies, le serveur envoie les canaux configurés via NotificationService (sans affecter la réponse JSON).
Translate — POST /api/translate¶
Traduit par lot les champs anglais title / description vers une locale UI via MyMemory / LibreTranslate / Ollama (voir Configuration). Utilisé quand la langue UI change après un scan ou pour des éléments au-delà des limites de traduction serveur lors du scan.
Requête :
{
"locale": "fr",
"items": [
{
"id": "CVE-2024-1",
"tool": "Redis",
"title": "Heap buffer overflow",
"description": "…"
}
]
}
Réponse : { "locale": "fr", "items": [{ "id", "tool", "title", "description" }] }
Max éléments par requête : TRANSLATE_BATCH_MAX (défaut 40).
Versioned API (/api/v1 only)¶
POST /api/v1/scan/stream (SSE), historique/tendances scans, tenants/stacks CRUD, GET /api/v1/discovery/kubernetes. Détails : chapitre EN.
Résumé des endpoints¶
| Méthode | Chemin | Description |
|---|---|---|
| GET | /api/health |
Liveness + flags (?detailed=true) |
| GET | /metrics |
Métriques Prometheus |
| GET | /api/capabilities |
Limites et fonctionnalités |
| GET | /api/sources |
Catalogue sources intégrées |
| GET | /api/openapi.json |
Spécification OpenAPI 3.1 |
| POST | /api/scan/validate |
Validation stack/sources uniquement |
| POST | /api/scan |
Scan complet |
| POST | /api/watch |
Poll watch + diff |
| POST | /api/translate |
Traduction par lot |
| POST | /api/v1/scan/stream |
Scan SSE (v1) |
| GET | /api/v1/scans/history |
Historique tenant |
| GET/POST | /api/v1/tenants/stacks |
Stacks enregistrées |
| GET | /api/v1/discovery/kubernetes |
Découverte K8s |
Alias /api/* pour scan/metadata de base ; routes v1-only listées ci-dessus.
Sécurité et déploiement¶
L’API est prévue pour des réseaux de confiance. Auth optionnelle : API_SECRET côté serveur ; les clients envoient X-Api-Key ou Authorization: Bearer. GET /api/health et GET /api/v1/health restent ouverts pour les sondes. Ne pas exposer sans TLS sur Internet public. Définissez NVD_API_KEY pour un débit plus élevé.
Chapitres associés¶
- Configuration — variables d’environnement
- Architecture — disposition des modules serveur
- Scan et watch — sémantique produit des modes
Essayez les requêtes dans l’onglet API Explorer.