Aller au contenu

Security CVE Watch

Security CVE Watch est un workflow N8N qui scanne quotidiennement les images Docker du VPS à la recherche de vulnérabilités connues (CVE), dédoublonne les détections et n’envoie une alerte que pour les nouveautés ou les escalades de sévérité.

WorkflowIDNodesRôle
CVE Watch (parent)5mHMlcg2HqEa7pWJ18Trigger + boucle images + agrégation + notification
CVE Scanner (SW-1)Tz40sFr3CMrw7X816Lance trivy image via SSH sur une image
CVE Processor (SW-2)JCyc4Jkev8fQ1mwL9Dédup, classification, comparaison historique

Data Tables

CVE Watch · 18 nodes

CVE Processor · 9 nodes

Lookup cve_notifications

Filter CRITICAL/HIGH

Insert/Update DT

CVE Scanner · 6 nodes

SSH Local VPS

docker exec trivy image <img>

Parse JSON output

Déclencheurs

Cron daily 06:00

Cron weekly Monday 09:00

DIUN webhook · nouvelle image

Get Docker Images · docker images

Loop Over Images

Aggregate Findings

Notification Hub

cve_notifications · Tfng3e4kUL0Ya4Lm

cve_scan_history · elUlUt9HzqSSCr7L

Une dizaine d’images de la stack VPS sont scannées : n8nio/n8n, odoo:18, caddy:2-alpine, postgres:16, postgres:17, redis:7-alpine, qdrant/qdrant, crowdsecurity/crowdsec, prom/prometheus, grafana/grafana. La liste est dérivée de docker images --format au runtime, donc les ajouts de stacks sont automatiquement intégrés au prochain scan.


Les CVE publiées sur les images Docker ne déclenchent rien automatiquement. Une vulnérabilité critique sur postgres:16 peut traîner des semaines avant d’être remarquée si personne ne consulte explicitement l’avis CVE ou ne lit le changelog du registre.

Symptôme sans CVE WatchCauseImpact
Vulnérabilité non détectéePas de scan systématiqueFenêtre d’exploitation prolongée
Faux positifs en bouclePas de dédupBruit, désensibilisation aux alertes
Déclenchement lentSurveillance manuelleAucun mécanisme de relance
Pas de traçabilitéPas d’historique de scanImpossible de prouver un état
CritèreTrivySnykDocker Scout
Open sourceOui (Apache 2.0)NonNon
Self-hostedOuiPartielNon
Sources CVENVD, Red Hat, Alpine, Debian, UbuntuNVD, Snyk DBNVD, Snyk DB
Auth requiseNonToken + quotaDocker Hub login
Scan offlineOui (DB locale)NonNon
Format JSONStable, documentéStableStable

Le choix de Trivy s’aligne avec la philosophie self-hosted du VPS : pas de dépendance à un SaaS, pas de quota d’API, pas de fuite de la liste des images vers un tiers.

TriggerFréquenceCas d’usage
Cron daily 06:00Tous les jours avant la journéeDétecter les CVE publiées la veille
Cron weekly Monday 09:00Une fois par semaineRécap hebdomadaire avec tendances
DIUN webhookÀ chaque pull d’imageScanner immédiatement une nouvelle version

Le couplage avec DIUN ferme la boucle : quand DIUN détecte une nouvelle image disponible, le scan CVE est déclenché avant l’approbation Telegram, ce qui permet de refuser un update qui introduirait une régression de sécurité.


1. Inventaire des images — Le parent appelle docker images --format '{{.Repository}}:{{.Tag}}' via SSH local pour obtenir la liste exacte des images chargées sur le VPS au moment du scan.

2. Boucle par image — Pour chacune, le parent appelle le sous-workflow CVE Scanner via Execute Workflow.

3. Scan Trivy — Le Scanner se connecte en SSH au VPS et lance docker exec trivy image --format json --severity CRITICAL,HIGH <image>. Le container trivy est pré-installé et son cache de DB CVE est monté en volume pour éviter de re-télécharger 150 MB à chaque scan.

4. Parsing du résultat — Le Scanner parse le JSON Trivy et retourne un tableau normalisé {cve_id, severity, package, installed, fixed, title, cvss}.

5. Dédup et classification — Le CVE Processor compare chaque finding avec la table cve_notifications. Trois cas :

CasAction
CVE inconnueInsert avec status=new, ajoute à la liste à notifier
CVE déjà notifiéeSkip (sauf escalade de sévérité)
CVE marquée fixéeVérifier que le fix est bien appliqué, sinon ré-ouvrir

6. Agrégation — Le parent regroupe les nouvelles findings par image et par sévérité.

7. Notification — Si au moins une CRITICAL est présente, le parent envoie une alerte immédiate au Notification Hub. Sinon, il attend le passage hebdomadaire pour un digest.

ColonneTypeDescription
cve_idstringCVE-YYYY-NNNNN
imagestringrepo:tag
severitystringCRITICAL / HIGH / MEDIUM / LOW
packagestringPaquet vulnérable
installed_versionstringVersion actuelle
fixed_versionstringVersion qui corrige (ou null)
first_seendatetimePremière détection
notified_atdatetimeDate de la dernière notification
statusstringnew / notified / fixed / ignored
ColonneTypeDescription
scan_datedatetimeDate du run
images_scannednumberNombre d’images analysées
critical_countnumberCVE CRITICAL détectées
high_countnumberCVE HIGH détectées
report_sentbooleanNotification envoyée ?

Alerte immédiate (CRITICAL) envoyée via le Notification Hub :

🚨 CVE CRITIQUE DÉTECTÉE
Image: postgres:16
CVE: CVE-2026-12345
Severity: CRITICAL (CVSS 9.8)
Package: libpq
Installed: 16.2 → Fixed in: 16.3
Stacks affectés:
- n8n-stack (n8n-postgres)
- odoo-stack (odoo-db)
[🔄 Update maintenant] [📖 Détails CVE] [⏰ Reporter]

Digest hebdomadaire envoyé chaque lundi 09:00 :

📊 CVE Watch · Semaine 18
12 scans effectués
0 CRITICAL · 3 HIGH · 8 MEDIUM (ignorées)
FIXES APPLIQUÉS:
✅ postgres:16.2 → 16.3 (CVE-2026-12345)
✅ caddy:2.8.4 → 2.8.5 (CVE-2026-12346)
EN ATTENTE:
⏳ redis:7.2.3 → 7.2.4 (planifié dimanche)

Quand DIUN détecte qu’une nouvelle version d’image est disponible, son webhook déclenche aussi CVE Watch sur cette image spécifique. Le résultat est intégré au message d’approbation Telegram :

CasBouton de l’approval
Nouvelle version sans CVE[Update] (vert)
Nouvelle version + CVE résolue[Update fixe CVE-XXX] (vert)
Nouvelle version + nouvelles CVE[Update malgré CVE] (orange)

L’utilisateur prend la décision en pleine conscience du risque.


LimiteImpactMitigation
Lag des feeds CVEUne CVE publiée hier peut ne pas être encore dans la DB TrivyCouplage avec abonnement RSS NVD à terme
Dépendances applicatives non scannéesTrivy scan les paquets OS, pas les dépendances package.json/requirements.txt à l’intérieur de l’imageCouvrir avec un workflow GitHub Dependabot séparé
Pas de scoring contextuelUn CVSS 9.8 sur un paquet inutilisé reste affiché comme CRITICALWhitelist par paquet via error_handling_config-like (à concevoir)
Faux positifs sur images muslTrivy classe parfois des CVE Debian sur des images Alpine (musl)Ignorer via filtre --ignore-policy Trivy

Si la fréquence quotidienne devient insuffisante :

  • Passer à un scan toutes les heures pour les images CRITICAL
  • Abonner CVE Watch à un flux NVD quasi-temps-réel
  • Coupler avec un webhook Trivy serveur (mode --server)

Si le bruit de notifications devient gênant :

  • Ajouter une whitelist par CVE acceptée (avec justification)
  • Regrouper les CVE par paquet plutôt que par CVE
  • Ne notifier que si CVSS ≥ 9.0 en mode strict

Si le besoin de conformité émerge :

  • Conserver les rapports JSON dans un bucket d’audit
  • Générer un PDF mensuel signé
  • Exposer une API read-only pour un dashboard externe
MétriqueSourceInterprétation
cve_critical_opencve_notifications WHERE status IN ('new','notified') AND severity='CRITICAL'Doit rester à 0
cve_mttrΔ entre first_seen et fixed_atMean Time To Resolution
scan_failurescve_scan_history WHERE images_scanned=0Indicateur de panne du scanner