POST /v1/organizations/{org_id}/projects/{id}/scans
Dépose le rapport d’un scanner de vulnérabilités pour un projet : JSON de Trivy, de Grype ou tout rapport CycloneDX qui porte des vulnérabilités, ou export d’un scanner réseau — Tenable Nessus (.nessus ou CSV), Greenbone/OpenVAS (rapport XML), Qualys VMDR (XML ou CSV), Rapid7 InsightVM/Nexpose (XML Export 2.0 ou CSV). C’est la seule route d’écriture de l’API : pensée pour la CI, à appeler à chaque déploiement.
Le scan devient une preuve datée (NIS2 : règlement d’exécution 2024/2690, annexe, § 6.10.2 b) et il est confronté aux fiches de suivi du projet : une CVE déclarée corrigée que le scan trouve encore est signalée « démentie », une CVE que rien ne suit est « hors suivi ».
POST /api/v1/organizations/{org_id}/projects/{project_id}/scans?fichier=trivy.jsonAuthorization: Bearer twa_votre_cle_iciContent-Type: application/json
{ …le rapport tel que le scanner l'a produit… }| Paramètre | Où | Description |
|---|---|---|
org_id |
chemin | Organisation de la clé |
project_id |
chemin | Projet scanné (dans la restriction de projets de la clé, s’il y en a une) |
fichier |
requête, facultatif | Nom du rapport, gardé dans la trace (255 caractères au plus) |
Le corps est le rapport brut, 20 Mo au plus (au-delà, 413 sans lecture du reste). Le format est reconnu au contenu : JSON, XML, puis CSV reconnu à sa ligne d’entête ; le Content-Type (application/json, application/xml, text/csv) n’est qu’indicatif. Le XML est lu sans entités ni références externes : un document qui en déclare est refusé (422).
Seules les vulnérabilités à identifiant CVE sont suivies ; une GHSA qui cite sa CVE lui est rattachée, les autres sont comptées (nb_hors_cve). Pour un scanner réseau, un constat qui cite plusieurs CVE donne une ligne par CVE, les constats purement informatifs sans CVE sont ignorés, et les doublons (même CVE, même hôte, même composant, même version) sont fusionnés.
outil |
Rapport |
|---|---|
trivy, grype, cyclonedx |
JSON |
nessus |
.nessus (XML v2) ou CSV |
openvas |
rapport XML Greenbone (GMP / GSA) |
qualys |
résultats de scan XML ou CSV, Asset Data Report XML |
insightvm |
XML Export 2.0 ou CSV |
Exemple de CI
Section intitulée « Exemple de CI »trivy image --format json -o trivy.json registry.exemple.fr/app:1.4curl -X POST "https://app.techwatchalert.com/api/v1/organizations/$ORG_ID/projects/$PROJECT_ID/scans?fichier=trivy.json" \ -H "Authorization: Bearer $TWA_API_KEY" -H "Content-Type: application/json" \ --data-binary @trivy.json
# Scanner réseau : l'export du dernier scan, tel quelcurl -X POST "https://app.techwatchalert.com/api/v1/organizations/$ORG_ID/projects/$PROJECT_ID/scans?fichier=parc.nessus" \ -H "Authorization: Bearer $TWA_API_KEY" -H "Content-Type: application/xml" \ --data-binary @parc.nessusRéponse 201 Created
Section intitulée « Réponse 201 Created »{ "scan": { "id": "018e8888-0000-7000-8000-000000000090", "project_id": "018e8888-0000-7000-8000-000000000010", "outil": "trivy", "cible": "registry.exemple.fr/app:1.4", "fichier": "trivy.json", "via": "api", "importe_par": null, "importe_le": "2026-09-25T08:30:00Z", "nb_constats": 3, "nb_hors_cve": 1 }, "constats": [ { "cve_id": "CVE-2024-37383", "composant": "roundcube/roundcubemail", "version": "1.6.6", "version_corrigee": "1.6.7", "severite": "MEDIUM", "actif": null, "actif_nom": null, "systeme": null, "port": null, "reference": null, "titre": null, "etat": "dementi" } ], "par_etat": { "dementi": 1, "ecartee": 0, "hors_suivi": 1, "suivie": 1, "acceptee": 0 }, "par_actif": [], "non_retrouvees": ["CVE-2023-51764"], "nb_non_retrouvees": 1}etat |
Signification |
|---|---|
dementi |
déclarée corrigée, encore détectée |
ecartee |
déclarée non applicable, détectée |
hors_suivi |
aucune fiche : le composant manque à la stack, ou la politique l’a filtré |
suivie |
fiche ouverte |
acceptee |
risque accepté : sa présence est attendue |
non_retrouvees : CVE suivies que ce scan ne trouve pas (corrigées, ou hors de ce qu’il couvre).
Scanner réseau
Section intitulée « Scanner réseau »Chaque constat porte en plus l’hôte et le test ; par_actif résume le scan hôte par hôte (CVE distinctes, dont démenties et hors suivi), les hôtes qui démentent un correctif d’abord. Ces champs valent null (et par_actif une liste vide) pour Trivy, Grype et CycloneDX.
{ "constats": [ { "cve_id": "CVE-2023-38408", "composant": "openbsd openssh", "version": "8.9p1", "version_corrigee": "9.3p2", "severite": "HIGH", "actif": "10.0.0.5", "actif_nom": "srv-web01.exemple.fr", "systeme": "Linux Kernel 5.15 on Ubuntu 22.04", "port": "22/tcp", "reference": "178911", "titre": "OpenSSH < 9.3p2 Vulnerability", "etat": "dementi" } ], "par_actif": [ { "actif": "10.0.0.5", "actif_nom": "srv-web01.exemple.fr", "systeme": "Linux Kernel 5.15 on Ubuntu 22.04", "ports": ["22/tcp", "443/tcp"], "nb_cve": 4, "nb_dementi": 1, "nb_hors_suivi": 2 } ]}| Champ | Contenu |
|---|---|
actif |
hôte : adresse IP, à défaut son nom |
actif_nom |
nom DNS ou NetBIOS |
systeme |
système d’exploitation détecté |
port |
port et protocole (443/tcp) ; null pour un constat d’hôte |
reference |
identifiant du test : plugin Nessus, OID Greenbone, QID Qualys, id Rapid7 |
titre |
intitulé du test |
composant |
produit détecté (CPE, empreinte de service), sinon intitulé du test |
| Code | Cause |
|---|---|
403 |
clé sans le droit scans, ou plan sans accès API |
404 |
projet hors de l’organisation ou de la restriction de la clé |
413 |
rapport de plus de 20 Mo |
422 |
rapport illisible : JSON ou XML malformé, XML qui déclare des entités ou des références externes, format non reconnu, plus de 20 000 vulnérabilités, ou SBOM sans vulnérabilités (à importer depuis la stack) |