Étude de cas · sécurité
122 → 0 CVE, et la racine n'était pas dans le code.
Premier passage d'audit sur quatre environnements Python de production. Le rapport initial annonçait 122 vulnérabilités connues. Ce qui suit est le détail complet : ce que j'ai trouvé, ce que j'ai eu tort de chercher d'abord, et le dispositif qui empêche aujourd'hui la récidive.
Contexte
Quatre environnements virtuels distincts, un par service en production : le gateway d'inférence, le RAG documentaire, l'agent de code, le pipeline musical. Chacun avec ses dépendances propres, tous installés progressivement sur plusieurs mois, aucun jamais audité.
C'est la situation normale d'un système qui a grandi par ajouts successifs. Personne ne décide un jour d'accumuler 122 vulnérabilités — elles arrivent une par une, chacune trop petite pour justifier un arrêt.
La contrainte
Aucun de ces environnements ne pouvait être reconstruit de zéro. Le gateway sert des modèles résidents dont le rechargement coûte environ deux minutes ; le RAG indexe 1,7 million de chunks. « On repart d'un requirements.txt propre » n'était pas une option — il fallait corriger sans casser ce qui tournait.
Ce que j'ai cherché en premier, et pourquoi c'était le mauvais endroit
Le réflexe est de trier par gravité et de commencer par les critiques. Je l'ai fait. C'était utile pour rassurer, inutile pour comprendre.
Le tri par gravité traite chaque vulnérabilité comme un événement indépendant. Or, sur un système assemblé, elles ne le sont pas : elles arrivent par grappes, parce qu'une même cause en produit plusieurs. Trier par gravité, c'est corriger des symptômes dans le désordre.
Le tri utile est par paquet et par environnement : quels paquets apparaissent dans plusieurs environnements, et pourquoi y sont-ils épinglés à des versions différentes ?
La racine réelle
Ce tri-là a fait apparaître une anomalie : plusieurs bibliothèques étaient bloquées à des versions périmées dans un seul environnement, alors que les trois autres les avaient à jour.
La cause n'était pas dans le code applicatif. C'était un outil en ligne de commande installé dans l'environnement virtuel du service. Cet outil n'avait rien à faire là — il ne servait qu'à des manipulations ponctuelles en développement — mais son installation avait imposé ses propres contraintes de version à des bibliothèques que le service utilisait aussi. Le résolveur avait fait son travail : il avait trouvé un jeu de versions compatible. Périmé, mais compatible.
Aucune lecture du code applicatif n'aurait trouvé ça. Le fichier fautif n'était importé nulle part.
Retirer l'outil de l'environnement du service et le déplacer dans un environnement dédié a débloqué d'un coup la majeure partie des mises à jour.
Ce qui a résisté
Trois CVE n'avaient aucun correctif amont. Le paquet était soit non maintenu, soit le correctif non publié.
La tentation est de les ignorer : elles ne sont pas exploitables dans ce contexte, le service tourne en boucle locale, le risque réel est faible. C'est probablement vrai. Le problème n'est pas l'évaluation du risque — c'est qu'une exception non écrite devient, six mois plus tard, une exception oubliée, et que plus personne ne sait si elle a été évaluée ou simplement subie.
Les trois sont donc tracées nommément, avec pour chacune : l'identifiant, le paquet, la raison de l'exception, la date de la prochaine revue. Elles sont revues chaque mois. Si un correctif amont paraît, l'exception tombe.
Le résultat, mesuré
| Avant | Après | |
|---|---|---|
| Vulnérabilités connues | 122 | 0 |
| Environnements audités | 0 | 4 |
| Exceptions tracées nommément | — | 3 |
| Dépôts sous pré-commit | 0 | 5 |
| Services interrompus | aucun | |
Ce qui empêche la récidive
Un nettoyage ponctuel ne vaut rien : les dépendances rebougent la semaine suivante. Trois dispositifs, du moins au plus contraignant :
- Pré-commit sur cinq dépôts — l'audit tourne avant que le commit ne parte, pas après.
- Une section d'audit dans l'éval nocturne — elle échoue au rouge à la moindre réapparition. Un verdict rouge n'est pas une notification à trier le lendemain : c'est un échec franc.
- La revue mensuelle des exceptions — trois lignes à relire, la seule tâche manuelle qui reste.
Transposable chez vous ?
Oui, et c'est exactement le périmètre de la prestation Audit. Ce qui se transporte n'est pas la liste des paquets — la vôtre sera différente — mais la méthode : trier par cause plutôt que par gravité, chercher ce qui n'a rien à faire dans l'environnement, nommer les exceptions plutôt que les tolérer, et poser un gate qui échoue au rouge.
Le chiffre à retenir n'est pas 122. C'est zéro service interrompu : un audit qui casse la production ne sera pas refait deux fois.
Vos données ne peuvent pas sortir ?
C'est exactement le problème que je résous. Un appel de 30 minutes suffit à cadrer un audit.