Blog

Un outil open-source en production : qui corrige la faille quand vous n'en écrivez pas le code ?

Fider pour les retours utilisateurs, Maildev pour les emails de recette : deux images Docker que nous exploitons sans en écrire une ligne. Voici comment nous savons si une CVE nous concerne, et ce que nous faisons quand l'éditeur ne bouge pas.

Mathieu Ducrot Mathieu Ducrot
|
|
11 min de lecture
| Tech
Résumez cette page avec votre IA préférée :

Introduction

Nous avons expliqué comment déployer un outil open-source sur Clever Cloud avec Docker : un dépôt Git, un Dockerfile de trois lignes, un add-on PostgreSQL. Le déploiement tient en une matinée. C’est la suite qui n’était pas écrite : une fois Fider en production, et Maildev sur les environnements de recette, qui s’assure qu’ils restent sûrs ?

La question n’est pas la même que pour un logiciel que nous développons. Sur une application Symfony, une CVE dans une dépendance se traite par un composer update et une recette. Sur Fider, nous n’écrivons pas une ligne de code : nous ne pouvons pas corriger, seulement mettre à jour, contourner ou accepter. Et l’éditeur, c’est une équipe de bénévoles ou une petite structure, qui ne doit rien à personne.

Cet article décrit la méthode que nous appliquons à ces outils. Elle repose sur trois idées : une CVE peut se loger à trois endroits distincts d’une image Docker tierce, un scan planifié suffit à les surveiller tous, et la réactivité de l’éditeur est une information sur la dépendance elle-même, pas seulement sur la faille.

1. Un outil tiers est une dépendance, à l’échelle d’un logiciel entier

Remplacer un SaaS par un outil open-source auto-hébergé a deux arguments solides, le coût fixe et la souveraineté des données. Nous les avons développés dans notre réflexion sur les alternatives aux logiciels SaaS. Ils ont une contrepartie que le prix du SaaS incluait sans le dire : chez un éditeur SaaS, quelqu’un surveille les failles, met à jour et redéploie. En auto-hébergement, c’est vous.

Ajouter Fider à une infrastructure revient donc à ajouter une dépendance, comme un bundle Symfony ou un paquet npm, avec la même question : est-ce que quelqu’un la maintient, et est-ce que nous saurons la suivre ? La différence est d’échelle. Un paquet npm, c’est quelques fichiers. Fider, c’est une application Go, un front React, une image Alpine, et un schéma de base de données avec ses migrations.

L’audit avant de choisir

La conséquence pratique, c’est que l’audit se fait avant le choix, pas après l’incident. Avant d’adopter un outil, nous scannons l’image candidate avec OSV-Scanner et nous la lançons en local pour un scan ZAP. Deux résultats possibles :

  • Rien de bloquant : l’outil est adopté, le tag de l’image est épinglé dans le Dockerfile, et la surveillance décrite plus bas démarre.
  • Une faille réelle : nous ouvrons un ticket sur le dépôt de l’éditeur, s’il n’existe pas déjà. La suite dit tout : un mainteneur qui répond dans la semaine et publie un correctif dans le mois est un mainteneur avec lequel on peut exploiter un outil pendant des années. Un ticket sans réponse est une réponse.

Nous ne conservons pas d’historique de ces audits. Le rapport sert à décider, puis le scan planifié prend le relais. Ce qui reste, c’est la décision : l’outil, le tag, et la date.

2. Les trois couches où une CVE peut se loger

C’est le point que la plupart des équipes découvrent au premier scan. L’image getfider/fider:v0.33.0 n’est pas « Fider » : c’est un empilement, et chaque couche a son propre calendrier de correctifs.

CoucheCe qu’elle contientOù la faille apparaîtQui corrige
L’outil lui-mêmeLe code Go de Fider, le code Node.js de MaildevAdvisory GitHub, CVE sur l’outilL’éditeur, dans une nouvelle version
Ses dépendancesModules Go, paquets npm embarqués dans l’imageOSV.dev, via le scan de l’imageL’éditeur, en recompilant avec la dépendance corrigée
L’image de basePaquets Alpine ou Debian : openssl, libcrypto, zlibOSV.dev, via le scan de l’imageL’éditeur, en reconstruisant sur une base à jour
Autour de l’imagePostgreSQL, TLS, réseau, plateformeHors du scanClever Cloud, dans le cadre de son contrat

Trois lignes sur quatre ont le même correcteur : l’éditeur. C’est la caractéristique du cas. Nous ne recompilons pas Fider, nous ne remplaçons pas ses modules Go, et nous verrons plus bas pourquoi nous ne reconstruisons pas non plus son image de base. Tout ce que nous pouvons faire, c’est détecter, qualifier, et attendre ou décider.

La quatrième ligne compte autant que les trois autres. Dire ce que nous ne scannons pas, PostgreSQL managé par l’hébergeur, la terminaison TLS, le socle de la plateforme, est ce qui rend crédible ce que nous scannons. C’est la même frontière que sur la page gestion des vulnérabilités : le périmètre de l’hébergeur relève de l’hébergeur.

3. Le scan hebdomadaire : une seule source, l’image qui tourne

Nous ne suivons pas les flux de releases, les listes de diffusion ni les comptes des éditeurs. Une seule source alimente la surveillance : le scan OSV de l’image, chaque semaine, sur le tag réellement déployé.

Le job est celui de notre article sur l’audit des Dockerfile, déclenché par une pipeline programmée GitLab. La seule adaptation est la cible : pas une image que nous construisons, mais le tag public épinglé dans le Dockerfile.

osv-scanner scan image getfider/fider:v0.33.0
osv-scanner scan image maildev/maildev:1.1.1

Ce choix d’une source unique se défend par ce que le scan couvre. OSV.dev agrège les advisories GitHub, la base Go, les paquets Alpine et Debian : une faille publiée sur un module Go de Fider ou sur openssl dans l’image y apparaît sans que nous ayons rien à lire. Le rapport indique pour chaque vulnérabilité la couche qui l’a introduite, la version corrigée quand elle existe, et le score CVSS.

Une limite à connaître : le scan reconnaît les dépendances par leur version. Une faille dans le code propre de l’outil, et non dans une de ses dépendances, n’est détectée que si elle est publiée comme advisory sur le dépôt de l’éditeur avec une plage de versions. C’est le cas des projets sérieux, et c’est un critère de plus pour choisir l’outil.

Le scan hebdomadaire sert aussi à la mise à jour de routine. Quand il tourne, nous comparons le tag déployé à la dernière version publiée par l’éditeur. Un écart de plusieurs versions mineures se rattrape lors de la prochaine fenêtre de maintenance, avant qu’une CVE ne vienne imposer son calendrier.

4. Le verdict : concerné, ou pas

Un rapport OSV sur une image Alpine remonte souvent une dizaine de vulnérabilités. La plupart ne concernent pas l’application qui tourne dessus. Le travail, celui que rien n’automatise, est d’écrire pour chacune un verdict et son motif. Trois questions suffisent presque toujours :

  1. Le composant est-il utilisé à l’exécution ? Fider est un binaire Go compilé statiquement. Une CVE dans curl ou dans un interpréteur présent dans l’image n’a pas de chemin d’exécution : Fider ne lance jamais de commande système. Verdict : non concerné, motif écrit.
  2. La fonction vulnérable est-elle atteignable ? Une faille dans le parseur d’un format que l’outil n’accepte pas en entrée n’est pas exploitable par un utilisateur. Le détail de l’advisory le dit presque toujours.
  3. Qui peut atteindre l’outil ? Fider est public par nature. Maildev est un outil de recette, derrière une authentification HTTP Basic, accessible à l’équipe seulement. La même CVE n’a pas la même sévérité sur les deux.

Le verdict se note dans le README.md du dépôt, celui que nous décrivons dans l’article de déploiement, à côté du tag déployé et de la date du dernier scan. Pas un rapport de plus, une ligne par CVE ouverte : l’identifiant, le verdict, le motif, et ce qu’on attend. C’est ce que nous sortons le jour où un questionnaire fournisseur demande « comment suivez-vous les vulnérabilités de vos composants tiers ».

5. Ce que nous faisons quand le verdict est « concerné »

Une seule réponse : la mise à jour vers la version de l’éditeur qui corrige. Dans l’ordre :

  1. Lire le changelog entre le tag déployé et la cible, à la recherche des ruptures : variable renommée, option de ligne de commande supprimée, migration de schéma. Pour Maildev, dont le Dockerfile passe ses options dans CMD, une option disparue au changement de version fait tomber le conteneur au démarrage.
  2. Sauvegarder la base avant toute montée de version de Fider. ./fider migrate s’exécute au démarrage du conteneur et certaines migrations de schéma ne se retournent pas. Sur Clever Cloud, une sauvegarde manuelle de l’add-on PostgreSQL prend une minute et se fait depuis la console.
  3. Modifier le tag dans le Dockerfile, et scanner la nouvelle image dans la merge request avec le même job OSV, cette fois bloquant : une image cible qui embarque elle-même une faille critique corrigeable n’est pas déployée.
  4. Déployer via le job deploy du pipeline, puis vérifier les logs de démarrage et le HEALTHCHECK.
  5. Valider avec ZAP, comme décrit à la section suivante.

Le scan hebdomadaire ne produit pas de correctif, mais il produit une date. « CVE-XXXX-YYYY, publiée le 3, verdict concerné le 5, corrigée par v0.34.0 déployée le 12 » : c’est la trace qui prouve un délai tenu, et elle s’écrit en une ligne au moment du travail.

Ce que nous ne faisons pas : reconstruire l’image de base

La tentation existe. Quand la faille est dans un paquet Alpine et que l’éditeur ne publie rien, deux lignes suffisent pour la faire disparaître du rapport :

FROM getfider/fider:v0.33.0
RUN apk upgrade --no-cache

Nous ne le faisons pas. À partir de là, l’image qui tourne n’est plus celle de l’éditeur, c’est la nôtre : il faut la construire, la scanner elle, et répondre de ce qu’elle contient. Nous avons remplacé une dépendance par une dépendance plus un fork. Et cela ne règle que la couche système : une faille dans un module Go de Fider reste entre les mains de l’éditeur quoi que nous fassions.

Surtout, cela masque l’information. Un éditeur qui laisse une CVE critique ouverte dans son image pendant des mois nous apprend quelque chose sur la dépendance, pas seulement sur la faille. C’est un sujet que nous détaillerons plus loin en section 7.

6. Valider avec ZAP : le logiciel en local, le déploiement en production

Un scan de dépendances dit ce que l’image embarque. Il ne dit pas comment l’outil se comporte face à une requête hostile. C’est le rôle d’un scan applicatif ZAP, et sur un outil tiers en production, il se découpe en deux.

Le scan actif se fait en local. Un docker compose avec le même tag que la production et un PostgreSQL vide suffit à lancer Fider sur le poste. ZAP peut alors envoyer ses vraies charges d’attaque, injections et manipulations de paramètres, sans risque : les données sont fausses, les emails ne partent nulle part. Ce scan valide le logiciel : c’est celui que nous lançons avant d’adopter un outil, et après chaque montée de version.

La production ne reçoit qu’un scan passif. ZAP observe les réponses sans rien attaquer : en-têtes de sécurité, attributs des cookies, informations exposées, redirection HTTPS. Un scan actif sur un outil qui crée des données et envoie des emails produirait des tickets fantômes et des notifications aux vrais utilisateurs. Ce scan valide le déploiement, ce que la configuration Clever Cloud et les variables d’environnement ont réellement produit. Il tourne après chaque déploiement.

Les deux scans répondent à deux questions différentes, et c’est pour cela qu’aucun ne remplace l’autre : « ce logiciel résiste-t-il » se pose en local, « ce déploiement expose-t-il quelque chose » se pose en production.

7. Quand la dépendance ne tient plus

Toute la méthode repose sur le sérieux de l’éditeur, mais parfois un éditeur de solutions open-source disparaît. Surtout dans le cas de projets maintenus par une poignée de personnes, qui changent parfois de voie professionnelle. Trois signaux doivent vous alerter :

  • Une CVE « concerné » sans version corrective au bout du délai que nous nous fixons pour sa sévérité. Le rapport hebdomadaire la remonte semaine après semaine, avec la même ligne dans le README.
  • Un ticket ouvert chez l’éditeur sans réponse. Pas une réponse négative, une absence : le dépôt est encore là, mais personne ne lit.
  • Un écart de versions qui ne se comble plus, parce que l’éditeur ne publie plus, ou parce que chaque montée de version casse quelque chose et que nous la repoussons.

Ce sont des informations sur la pertinence de la dépendance, et il faut refaire l’analyse de la pertinence de l’outil le jour où elles apparaissent. Parfois on remet le choix de l’outil sur la table, on cherche l’équivalent maintenu, et on repasse par l’audit de la section 1 avant de remplacer. Un outil tiers qui ne se maintient plus est exactement le problème que le remplacement du SaaS voulait éviter, avec la facture en moins et la responsabilité en plus. Il vaut mieux le voir dans un rapport hebdomadaire que dans un questionnaire de sécurité.

Conclusion

Exploiter un outil open-source que l’on n’a pas écrit demande a priori moins de travail qu’un logiciel sur mesure, mais cela ne veut pas dire que c’est réellement gratuit. La méthode tient en peu de choses si l’éditeur est de qualité : un tag épinglé, un scan OSV hebdomadaire sur l’image qui tourne, un verdict écrit par CVE, une mise à jour qui passe par le changelog, la sauvegarde et un scan de l’image cible, un ZAP actif en local et passif en production. Et une règle : on ne reconstruit pas l’image de l’éditeur, parce que sa réactivité est une information qu’il ne faut pas masquer.

C’est ce qui fait de l’auto-hébergement une alternative au SaaS qui peut tenir dans le temps, et pas seulement le jour du déploiement. Si vous exploitez des outils de ce type sans savoir qui répondrait à la question « cette CVE vous concerne-t-elle », notre page sur la gestion des vulnérabilités décrit ce que nous mettons en place, et sous quels délais.

Liens utiles

Mathieu Ducrot
Mathieu Ducrot CTO
Mots clés :
#DevOps#Qualité

Articles similaires

Vous avez un projet ?

Contactez-nous pour savoir comment nous pouvons vous aider.