Chapitre 12.1 — CVE, audit & Dependabot
⏱️ TL;DR — Le risque le plus courant de la supply chain : utiliser une dépendance avec une vulnérabilité connue (une CVE publiée). Comme la faille est documentée, elle est facile à exploiter en masse — les attaquants scannent les applis qui embarquent la version vulnérable. La parade est mécanique : détecter (
npm audit,composer audit, bases d’avis) et corriger vite (mettre à jour). On automatise avec Dependabot/Renovate (qui ouvrent des PR de mise à jour) et on intègre l’audit à la CI (build cassé sur vulnérabilité critique). Clé : ne pas laisser traîner — une CVE connue non patchée est une porte grande ouverte, comme une instance Moodle en retard (Partie 11).
🎯 Objectifs
- Comprendre ce qu’est une CVE et pourquoi une vulnérabilité connue est dangereuse.
- Utiliser
npm audit/composer auditpour détecter les dépendances vulnérables. - Automatiser les mises à jour avec Dependabot/Renovate.
- Intégrer l’audit à la CI et prioriser les correctifs.
CVE : une faille connue est une faille exploitée
Une CVE (Common Vulnerabilities and Exposures) est un identifiant public d’une vulnérabilité connue dans un logiciel (ex. « telle version de tel paquet permet une RCE »). Les CVE sont publiées dans des bases d’avis de sécurité (advisory databases) que les outils consultent.
Le paradoxe déjà vu en Partie 11 : dès qu’une vulnérabilité est publiée (avec son correctif), elle devient facile à exploiter — les détails sont documentés, des exploits circulent, et les attaquants scannent massivement Internet à la recherche d’applis qui utilisent encore la version vulnérable. Une dépendance vulnérable non mise à jour n’est donc pas un risque théorique : c’est une cible active. Beaucoup de compromissions majeures ont exploité une CVE connue depuis des mois, simplement pas patchée.
💡 Réflexe — Traite une CVE dans une de tes dépendances comme une porte ouverte à refermer vite, pas comme une notification à ignorer. Le risque n’est pas « qu’on découvre » la faille (elle est déjà publique) mais qu’on tarde à l’appliquer. La vitesse de patch est une mesure de sécurité à part entière : entre la publication d’un correctif et l’exploitation de masse, la fenêtre est courte.
Détecter : audit
Les gestionnaires de paquets intègrent une commande d’audit qui compare tes dépendances (directes et transitives) aux bases d’avis :
# Node / npm
npm audit # liste les vulnerabilites connues, par severite
npm audit --audit-level=high # ne remonte que high/critical (utile en CI)
npm audit fix # applique les correctifs compatibles (mises a jour mineures)
# PHP / Composer
composer audit # signale les paquets vulnerables
# (Symfony : symfony check:security)L’audit classe les vulnérabilités par sévérité (low → critical). On priorise les critical/high (surtout si le paquet est exposé aux entrées ou exécuté). Attention : npm audit fix ne corrige que ce qui est compatible ; une CVE dans une dépendance profonde peut exiger une mise à jour majeure (avec adaptations) — à planifier, pas à repousser indéfiniment.
Automatiser : Dependabot / Renovate
Auditer manuellement ne suffit pas à l’échelle : de nouvelles CVE sortent en continu. On automatise avec des bots qui surveillent tes dépendances et ouvrent des pull requests de mise à jour :
- Dependabot (intégré à GitHub) : détecte les dépendances obsolètes/vulnérables et propose des PR (mise à jour de version), avec le changelog. Configurable (fréquence, groupes, écosystèmes).
- Renovate : équivalent très configurable (regroupement de MAJ, règles fines), multi-plateforme.
Ces bots transforment la mise à jour en flux continu de petites PR, testées par ta CI, plutôt qu’en « grand chantier » repoussé. L’important est de traiter ces PR (les revoir, les merger), pas de les laisser s’accumuler.
# .github/dependabot.yml (exemple minimal)
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule: { interval: "weekly" }
- package-ecosystem: "composer"
directory: "/"
schedule: { interval: "weekly" }Intégrer à la CI
Le maillon décisif : rendre l’audit bloquant dans la CI, pour qu’une vulnérabilité connue empêche le déploiement d’une nouvelle version.
# Etape CI : echouer si une vulnerabilite high/critical est presente
- run: npm ci
- run: npm audit --audit-level=high # casse le build si high/critical
# (cote PHP : composer audit)Ainsi, on ne livre pas de code qui embarque une faille connue grave, et on est forcé de traiter le problème (mettre à jour, ou justifier/mitiger). On combine avec Dependabot (flux de MAJ) et une installation reproductible (npm ci, lockfile — chapitre 12.2).
⚠️ Piège — Deux pièges opposés. (1) Ignorer les alertes (« ça marche, on verra plus tard ») : les CVE connues s’accumulent et une exploitation devient triviale. (2) Auto-merger aveuglément toutes les MAJ (y compris majeures) sans tests ni revue : une mise à jour peut casser l’appli, voire — cas rare mais réel — introduire une version compromise (chapitre 12.2). Le bon équilibre : audit bloquant en CI, Dependabot pour le flux de PR, tests qui valident chaque MAJ, et revue (surtout pour les majeures et les paquets sensibles). Ni négligence, ni automatisation aveugle.
🎯 Côté attaquant — L’attaquant n’a souvent rien à inventer : il prend une CVE publiée (avec exploit disponible) et scanne les applis qui embarquent la version vulnérable — parfois détectable via des fichiers exposés (
package-lock.json, en-têtes, comportements), parfois en testant l’exploit directement. Compromettre une appli via une dépendance obsolète est moins coûteux que de trouver une faille dans ton code. Une dépendance critique en retard de plusieurs mois est un cadeau. La vitesse de patch décide de qui gagne la course.
🧭 Sur FormaCampus — FormaCampus rend l’audit bloquant en CI (
npm audit --audit-level=highetcomposer audit), avec Dependabot activé sur les écosystèmes npm et Composer (PR hebdomadaires, testées par la CI). Les PR de sécurité sont priorisées (traitées en quelques jours, pas laissées s’accumuler) ; les mises à jour majeures passent par une revue et des tests. Un tableau de bord suit les dépendances obsolètes. Résultat : une CVE publiée dans une dépendance est détectée et corrigée rapidement, avant qu’un scanner ne trouve l’instance vulnérable — la même discipline que pour les mises à jour de Moodle (Partie 11).
✏️ Exercices
Exercice 1 — Pourquoi la vitesse compte. Une équipe reçoit une alerte : une dépendance a une CVE critique (RCE), corrigée dans la version suivante. Un dev propose de « voir ça au prochain sprint dans trois semaines ». Argumente contre.
✅ Solution
Attendre trois semaines est dangereux : la CVE est déjà publique (publiée avec son correctif), donc les détails et souvent un exploit sont disponibles, et les attaquants scannent activement Internet pour trouver les applis qui utilisent encore la version vulnérable. Pour une RCE critique, une exploitation réussie signifie une prise de contrôle du serveur (et des données d’apprenants). Le risque n’est pas « qu’on découvre » la faille (c’est fait), mais qu’on tarde à patcher pendant que la fenêtre d’exploitation est ouverte. La bonne réponse : appliquer la mise à jour immédiatement (ou dans les plus brefs délais après un test rapide), en priorité sur le reste du sprint — une CVE critique est un incident potentiel, pas une tâche de backlog. La vitesse de patch est une mesure de sécurité.
Exercice 2 — Durcis le processus. Une CI fait juste npm install et déploie. Quelles deux mesures ajouter pour gérer les vulnérabilités de dépendances ?
✅ Solution
(1) Ajouter npm audit (bloquant) à la CI — ex. npm audit --audit-level=high — pour que le build échoue si une vulnérabilité grave est présente, empêchant de livrer du code avec une CVE connue. (2) Activer Dependabot/Renovate pour recevoir en continu des PR de mise à jour (testées par la CI), et traiter ces PR rapidement (revue + merge), en priorisant les correctifs de sécurité. Bonus : remplacer npm install par npm ci (installation reproductible du lockfile, chapitre 12.2). Ensemble : détection (audit), correction continue (bot), reproductibilité (lockfile).
🧠 Quiz de révision
1. Qu’est-ce qu’une CVE et pourquoi une faille connue est-elle dangereuse ?
Une CVE est un identifiant public d’une vulnérabilité connue. Une faille connue est dangereuse car documentée (détails, souvent exploit disponible) : les attaquants scannent les applis qui utilisent la version vulnérable. Le risque est de tarder à patcher, pas que la faille soit découverte (elle est publique).
2. Comment détecte-t-on les dépendances vulnérables ?
Avec npm audit (Node) / composer audit (PHP), qui comparent tes dépendances (directes et transitives) aux bases d’avis et classent par sévérité. On priorise les critical/high. npm audit fix applique les correctifs compatibles.
3. À quoi servent Dependabot / Renovate ?
À automatiser la surveillance et les mises à jour : ils ouvrent des pull requests de mise à jour (testées par la CI), transformant le patching en flux continu de petites PR plutôt qu’en grand chantier repoussé. Il faut traiter ces PR (revue + merge), pas les laisser s’accumuler.
4. Pourquoi intégrer l’audit à la CI ?
Pour rendre l’audit bloquant : une vulnérabilité connue grave empêche le déploiement (npm audit --audit-level=high casse le build). On ne livre pas de code embarquant une CVE critique, on est forcé de la traiter (mettre à jour ou mitiger).
5. Quel est l’équilibre à trouver avec les mises à jour automatiques ?
Entre ignorer les alertes (CVE qui s’accumulent) et auto-merger aveuglément (risque de casse, voire de version compromise). Le bon équilibre : audit bloquant en CI, Dependabot pour le flux de PR, tests qui valident chaque MAJ, et revue des majeures/paquets sensibles.
Chapitre suivant : Typosquatting & lockfiles — l’autre menace : non pas une faille dans un paquet légitime, mais un paquet malveillant ou compromis installé chez toi.