Quand on parle des dépendances d’un développement, on parle principalement des bibliothèques externes sur lesquelles le projet est basé, et dont il dépend. Pour que le projet fonctionne, il faut que ces dépendances soient satisfaites, que le code source du projet y ait accès lorsqu’il en a besoin.
J’ai en têtes plusieurs choses, notamment des anecdotes intéressantes, mais aussi des réflexions plus sérieuses, concernant les dépendances, ce qu’elles impliquent et comment les aborder.
En préambule
Quand on parle de dépendances, il y a une image qui revient toujours − et je ne vais pas y faire exception − publiée sur XKCD en 2020 :
(si vous voulez une explication de texte, le site Explain XKCD est là pour vous aider)
Et je vais illustrer cette image avec quelques cas notoires de projets qui constituent (ou ont constitué) des petites cales de ce genre, et qui ont parfois fait basculer d’autres projets qui dépendaient d’eux.
2011 : timezone database (Unix)
La « timezone database » est la base de données (et la bibliothèque de référence de traitement de cette base) qui contient les informations concernant les fuseaux horaires et les passages heure d’été/heure d’hiver à travers la planète. Ce projet a été créé en 1986 par Arthur David Olson, et il est encore aujourd’hui le principal contributeur au code de la bibliothèque. Il a été rejoint par des contributeurs, dont Paul Eggert, qui a proposé en 1993 une normalisation des noms utilisés, et qui constitue toujours le mainteneur principal des données de la base.
La gestion du temps est quelque chose de bien plus complexe qu’on ne le pense au premier abord. Globalement, sans le travail de ces deux hommes (et surtout maintenant celui de Paul Eggert et de quelques autres contributeurs), ce serait vraiment la merde. Et d’ailleurs, leur travail est utilisé dans un très grand nombre de logiciels, langages de programmation, bases de données, etc.
Et en octobre 2011, la base a été coupée (mailing-list et serveur FTP inaccessibles) à cause d’une action en justice menée par l’éditeur de certains des atlas qui ont été utilisés pour constituer les données de la base.
Qu’on soit d’accord ou non avec leurs arguments, cette action aura au moins eu le mérite de mettre un coup de projecteur sur ce projet qui n’était qu’un hobby pour ses contributeurs, mais qui est essentiel à l’ensemble des systèmes informatiques de la planète. En conséquence, le projet a été repris par l’ICANN, lui offrant une structure officielle.
Au final, le cas a été réglé à l’amiable en février 2012 grâce à la participation de l’Electronic Frontier Foundation, l’éditeur attestant qu’il ne poursuivra plus à l’avenir. Tout est bien qui finit bien, mais si l’interruption avait duré longtemps, on aurait commencé à avoir des problèmes à travers la planète qu’il aurait été difficile à anticiper.
2014 : OpenSSL (Unix)
Autre projet intéressant, OpenSSL, qui fournit les bibliothèques libcrypto et libssl. Il a été créé en 1998, prenant la suite de la bibliothèque SSLeay. OpenSSL est le fruit du travail de Steve Marquess et Steven Henson ; le premier s’occupe des partenariats, des contrats et des relations avec le gouvernement américain, alors que le second a contribué à la grande majorité du code source.
Il faut bien voir que OpenSSL est la brique principale de sécurisation des échanges sur Internet, qu’il s’agisse de manipuler les certificats SSL (pour sécuriser les sites web) ou d’encrypter des échanges en utilisant un grand nombre d’algorithmes très performants. Comme expliqué dans cet article, ils ont longtemps fait un travail de moine, travaillant dessus en échange de très peu de reconnaissance ; avant la création de la OpenSSL Software Foundation en 2013, dans le but d’en financer le développement, Steven Henson gagnait environ 20 000 $ par an…
En avril 2014, la faille Heartbleed est découverte. Il apparaît alors qu’il est possible, dans certaines conditions, de récupérer les clés privées utilisées sur un serveur dans le cadre du protocole TLS. La situation semble catastrophique, car ce sont les fondements de la sécurisation des échanges sur Internet qui sont touchés.
En même temps, il est difficile d’en vouloir à deux gars qui font ce qu’ils peuvent en étant sous-financés.
Là encore, cela a amené à une prise de conscience générale, qui mènera la Linux Foundation à créer la Core Infrastructure Initiative (aujourd’hui la Open Source Security Foundation), financée par des entreprises qui ont tout intérêt à ce que les bases techniques sont lesquelles elles font leur business soient fiables (Google, Microsoft, Facebook, AWS, etc.). Grâce à cette initiative, le développement d’OpenSSL est financé à hauteur de 550 000 dollars par an (tout comme d’autres briques essentielles, comme GPG, NTPd et OpenSSH).
2016 : left-pad (Javascript)
L’histoire de la bibliothèque left-pad est assez édifiante. Quand elle est survenue en 2016, elle a été résumée par plusieurs articles comme “Comment un développeur a cassé Node, Babel et des milliers de projets en 11 lignes de Javascript”, ou encore “Comment un développeur a cassé Internet en effaçant un petit bout de code”.
Reprenons depuis le début. Azer Koçulu est un développeur qui proposait plusieurs bibliothèques sous licence libre, disponibles sur GitHub et via NPM (le gestionnaire de dépendances de NodeJS). Parmi ses nombreuses bibliothèques, l’une d’elles s’appelait “kik”.
En mars 2016, la société canadienne Kik Interactive, éditeur de la messagerie instantanée Kik Messenger, contacte Koçulu pour lui demander de leur abandonner le nom de bibliothèque “kik”, disant que les utilisateurs pourraient faire une confusion entre son projet et leur entreprise, et précisant avoir déposé la marque de manière internationale.
Koçulu refuse, argumentant qu’il existe des centaines d’autres bibliothèques dans le même cas (en donnant l’exemple du package nommé “square”). Kik Interactive lui demande quelle compensation pourrait faciliter les choses, il demande 300 000 dollars.
Faisons un petit arrêt ici. Sur le fond, les deux ont raison et tort. Koçulu est animé par l’amour du logiciel libre ; Kik doit faire valoir ses droits sur sa marque pour ne pas risquer de la perdre. En même temps, le développeur semble être parfois instable (voir ici et ici) ; de l’autre côté, en mars 2016 (tiens, la coïncidence est amusante) plus de 200 groupes de discussion ont été découverts sur Kik, dédiés à la distribution et à la vente de pédopornographie…
Bref, Kik ne semblait pas vouloir payer la somme demandée − alors qu’elle avait levé 120 millions de dollars à cette date − donc son responsable des brevets a contacté directement l’entreprise npm Inc. pour réclamer la possession du package “kik”.
Là, on peut déjà s’étonner d’apprendre que le gestionnaire de dépendances de NodeJS, qui est un très important logiciel open source, appartient à une entreprise…
La société NPM décide alors que la société Kik est dans son bon droit, et décide de lui transférer la propriété du package “kik” (l’ensemble des échanges est disponible, et npm a donné ses explications).
Ulcéré de voir les intérêts des développeurs bafoués au profit des entreprises, Koçulu décide d’effacer son compte NPM, et donc d’en retirer tous ses packages. Il s’expliquera en disant qu’il a “libéré ses modules”, car NPM est une propriété privée où les entreprises ont plus de pouvoir que le peuple, alors qu’il fait des logiciels libres pour donner le pouvoir au peuple. Il ajoute qu’il est toujours possible d’utiliser directement le code dans les dépôts GitHub, et qu’il est prêt à transférer la propriété de ses modules à qui voudra les maintenir.
Le problème, c’est que parmi ses modules, il y en a un nommé “left-pad”, qui ne contient que 11 petites lignes de code, et qui est utilisé par un grand nombre de projets, y compris des projets importants comme Node, Babel ou React. Évidemment, ces projets n’ont pas directement besoin de left-pad ; ils ont une dépendance qui a une dépendance qui a une dépendance… qui dépend de left-pad.
Des milliers de développeurs, ainsi que des entreprises comme Facebook, Paypal, Netflix, Spotify (et même Kik Interactive, c’est cocasse) se sont retrouvés d’un coup à ne plus pouvoir déployer leurs projets car l’une de leurs nombreuses sous-sous-dépendances était devenue indisponible.
En réaction, NPM a republié en urgence le package de Koçulu. On peut voir que, à la suite de ça, le package “kik” n’appartient pas à l’entreprise Kik Interactive, qui de son côté a publié un package “@kikinteractive/kik” qui n’a pas intéressé grand monde. Tout ça pour ça, bravo !
NPM a aussi changé ses règles concernant l’effacement de bibliothèques publiées, pour éviter que ce genre d’incident se renouvelle.
2020 : core-js (Javascript)
Encore une histoire trouble autour d’une dépendance Javascript. Denis Pushkarev est un développeur russe qui a créé en 2014 la bibliothèque “core-js”, qui fournit des polyfills, c’est-à-dire qu’elle offre aux navigateurs anciens du code qui se substitue aux fonctionnalités des navigateurs modernes. Cela permet donc aux développeurs d’écrire du code moderne sans avoir à se demander s’il fonctionnera partout.
Cette bibliothèque est la plus complète en la matière, et est très utilisée. C’est une dépendance pour tous les principaux frameworks Javascript (Angular, React, Vue), et elle est téléchargée 43 millions de fois par semaine. 75 % des 100 plus importants sites web l’utiliseraient. D’après son auteur, la seule bibliothèque Javascript plus utilisée que la sienne serait jQuery. C’est assez impressionnant.
Pushkarev est un passionné. Il travaille nuit et jour sur son projet, car il estime œuvrer à l’amélioration du web (et donc rendre le monde meilleur). Il vivote, mais ne trouve pas le poste dont il rêve, qui lui permettrait d’être payé pour maintenir core-js.
En avril 2019, il renverse deux femmes ivres sur la route, et l’une des deux décédera de ses blessures. Il s’expliquera dans un post de blog caché dans la documentation de core-js.
L’un dans l’autre, il lui fallait payer 80 000 dollars aux familles des victimes s’il voulait éviter la prison. Il a donc essayé de monétiser son travail. Il a fait en sorte qu’à chaque installation de sa bibliothèque avec npm, un message apparaisse proposant de le soutenir financièrement.
La communauté n’a, semble-t-il, pas bien réagi du tout à cela, et le retour de flamme a été violent. Il dit avoir reçu une avalanche de messages haineux. Juste à cause de quelques pauvres lignes qui s’affichent dans le terminal, sérieusement ?
In fine, il n’a pas réussi à collecter l’argent nécessaire, donc il est allé en prison en janvier 2020. Dans les mois qui précédèrent, il chercha quelqu’un qui pourrait assurer la maintenance du projet en son absence, mais personne ne semblait suffisamment intéressé.
Sa peine a été écourtée, il est resté emprisonné pendant 10 mois.
Certaines personnes prennent position en faveur de Pushkarev, d’autres y voient un mélodrame inutile. Quand on met son code sous licence libre, il faut accepter l’idée que les gens l’utilisent sans payer. Mais d’un autre côté, il n’y a rien de problématique dans le fait qu’un développeur propose de lui donner de l’argent (si on peut donner de l’argent à des youtubeurs sur Patreon, on peut bien le faire pour des développeurs sur OpenCollective, non ?).
Mais s’il avait passé des années en prison, qu’est-ce qu’il se serait passé ? On se dit que quelqu’un d’autre reprendrait le flambeau avec la même abnégation ? Manifestement non, puisqu’il n’a pas trouvé de remplaçant… C’est donc potentiellement des milliers de sites et applications web qui auraient connu des soucis.
2021 : Log4J (Java)
Fin novembre 2021, une faille sur la bibliothèque Log4J a été remontée par l’équipe de sécurité d’Alibaba à la fondation Apache, qui avait pris la main sur ce projet créé en 2001. La faille existait depuis 2013, et touchait 93% des environnements cloud (potentiellement des centaines de millions de systèmes).
Log4J est une bibliothèque d’écriture de logs, complètement hégémonique dans l’univers Java, au point de devenir un standard de fait (et que beaucoup de gens pensent qu’elle fait partie de la bibliothèque standard du langage), expliquant pourquoi le problème touchait la quasi-totalité des applications Java. La faille permettait d’exécuter du code distant et de récupérer des informations privées sur les systèmes, dans le cas où des données provenant des utilisateurs étaient loguées (ce qui arrive malheureusement trop souvent sans vérification). Cette faille était particulièrement facile à exploiter, et l’a été par plusieurs groupes de hackers, certains gouvernementaux (Chine et Iran), d’autres criminels à des fins de ransomware, d’autres enfin à seuls buts de destruction des systèmes.
La faille, nommée Log4Shell, a été qualifiée de « the single biggest, most critical vulnerability ever », « the most severe vulnerability ever », « extremely critical threat situation », « a true cyber-pandemic »…
Des corrections ont été publiées dans les deux semaines qui ont suivi la publication de la faille. Mais la mise à jour des systèmes a pris du temps, sans compter que des systèmes mis à jour avaient déjà été corrompus.
On peut remarquer que le développement de Log4J était réalisé par des développeurs sur leur temps libre, et financé par seulement 3 sponsors (des individus, pas des entreprises)… Le nombre est monté à 14 suite à la faille, mais on peut se demander si plus de ressources n’auraient pas été nécessaires, d’autant qu’il semblerait qu’un audit de sécurité à 100 000 dollars aurait suffi à débusquer la faille.
2022 : colors.js et faker.js (Javascript)
Il semblerait que l’univers Javascript est rempli d’histoires croustillantes ayant eu des répercussions importantes au niveau mondial. Marak Squires est un développeur qui proposait plusieurs packages sur npm, dont colors.js (gestion des couleurs et styles de caractères dans la console) et faker.js (génération de données de test). Ces deux bibliothèques étaient très utilisées, avec 27 millions de téléchargements hebdomadaires et 19 000 packages qui dépendent de colors.js, et 3 millions de téléchargements hebdomadaires et 2 500 packages qui dépendent de faker.js.
Squires n’avait déjà pas forcément une très bonne réputation. Fin 2020, il commentait son projet faker.js en disant qu’il ne voulait plus que son travail soit utilisé gratuitement par les grosses sociétés, alors qu’il l’avait placé sous licence MIT (une licence libre très permissive).
En avril 2021, il expliquait dans un post de blog comment il avait essayé de créer un service SaaS qui offre les fonctionnalités de faker.js au travers d’une API. Il raconte sa grande désillusion lorsqu’il s’aperçut que Retool, une entreprise éditant un outil nocode, avait créé un concurrent de son service en utilisant sa bibliothèque. Assez remonté, il a proposé au patron de Retool d’acheter la propriété intellectuelle de faker.js ; après un premier retour, il ne reçut plus aucune réponse.
Le CEO de Retool s’est expliqué par la suite. En gros, il avait réfléchi et n’était finalement pas intéressé, et a oublié de répondre.
Sauf que Squires semble avoir ruminé la chose pendant quelque temps. En janvier 2022, il a modifié faker.js et colors.js pour y intégrer des bombes logicielles sous forme de boucles infinies affichant n’importe quoi dans le terminal, rendant un grand nombre de développements complètement inutilisables. Des bibliothèques de substitution sont rapidement apparues, mais entre-temps de nombreux projets se retrouvèrent bloqués car dépendants de colors.js, comme aws-cdk (2 millions de téléchargements par semaine) − pour n’en citer qu’un.
2024 : XZ et libzma (Unix)
Lasse Collin est un développeur finlandais qui a créé, avec quelques autres personnes, le package XZ Utils, qui contient la bibliothèque de compression liblzma (qui utilise l’algorithme LZMA comme son nom l’indique) et le logiciel de compression XZ qui utilise cette librairie. Depuis 2009, le format de fichier “.xz” s’est répandu, devenant très utilisé, aussi bien par le kernel Linux que pour la sauvegarde de données.
À partir d’octobre 2021, un développeur du nom de Jia Tan commence à contribuer au code source, pour ajouter des fonctionnalités et corriger des bugs. Il faut savoir que Collin travaille sur le projet sur son temps libre, qu’il n’est pas rémunéré pour ça, et que (comme pour beaucoup d’autres contributeurs open source) il manque de temps. Au fil de ses contributions, Jia Tan gagne la confiance de Collin.
Là où on se rend compte que tout ça était planifié, c’est que des messages provenant d’autres personnes (enfin, qui se présentaient comme telles) exprimaient des plaintes quant à la lenteur des évolutions. Sous leur pression croissante, Collin finit par donner à Jia Tan le rôle de co-mainteneur du projet fin 2022.
La suite de l’histoire est un peu complexe (tout l’historique est détaillé ici, traduit ici). Pour simplifier, Jia Tan a compilé en mars 2024 une version vérolée de la liblzma, qu’il a envoyée aux distributions Linux en les pressant de l’intégrer, sous prétexte que cette version corrigeait un bug (qu’il avait préalablement introduit). Dans l’urgence, les distributions ont effectivement intégré les fichiers à leurs versions de test.
Il se trouve que plusieurs distributions Linux (Debian, Fedora, Red Hat, OpenSuse, Gentoo, Arch et leurs dérivées) modifient OpenSSH pour qu’il utilise libsystemd, afin de profiter des fonctionnalités de systemd pour gérer OpenSSH. Le problème, c’est que libsystemd charge à son tour liblzma.
La modification effectuée faisait que liblzma introduisait une porte dérobée dans OpenSSH, permettant de faire exécuter du code distant sur le serveur touché. Potentiellement, cela rendait vulnérables une écrasante majorité des serveurs qui tournent dans le monde.
La backdoor n’a pas été commitée dans le code source public. Seules les versions compilées par Jia Tan comportaient la modification. Et donc, il est intéressant de constater que les distributions Linux n’ont pas recompilé la bibliothèque à partir de ses sources, mais elles ont directement intégré les fichiers binaires fournis par Jia Tan. C’est en soi une erreur grossière, car elles ont accepté un code qu’elles ne pouvaient pas auditer.
Le plus incroyable dans cette histoire, c’est la manière dont la faille a été découverte. Un ingénieur de Microsoft, développeur sur PostgreSQL, faisait du microbenchmarking sur sa machine, ce qui l’a amené à voir une latence de 500 millisecondes provenant d’OpenSSH… Il a pu lancer l’alerte de sécurité, et les distribution Linux ont retiré le code corrompu avant qu’il ne se retrouve dans leurs version stables. On est passé pas loin d’une catastrophe mondiale.
Que penser de tout ça ?
Des gens disent que “le logiciel libre est cassé”, à cause de tous ces cas de défaillances causées par le sous-financement de projets qui sont devenus importants au fil du temps. Le sujet est assurément très important, mais en même temps on voit pas mal de logiciels libres qui s’en sortent très bien financièrement, portés par des fondations ou des entreprises privées ; ou encore des projets qui sont développés bénévolement par une ou plusieurs personnes, qui en bénéficient indirectement pour trouver un poste ou des contrats (le fameux « c’est quoi ton GitHub, je vais jeter un œil à tes repos« ).
D’ailleurs, il semblerait que les entreprises sont désireuses de financer les projets open source qui ont besoin de ressources pour améliorer la sécurité globale de leurs systèmes. Mais le problème réside dans l’identification des projets qui sont assez importants et fondamentaux pour valoir la peine, qui ont des risques de failles, qui sont sous-financés, et qui bénéficieraient d’une aide financière.
Un aspect qui m’intéresse, c’est… la dépendance aux dépendances.
Je vous invite à lire l’article “NPM & left-pad: Have We Forgotten How To Program?”. Son auteur part de l’exemple de left-pad (que j’ai détaillé plus haut), en le complétant avec d’autres exemples tout aussi caricaturaux, pour se demander si la manière dont on développe aujourd’hui ne serait pas complètement faussée.
De nos jours (et en fait ce n’est pas si nouveau, l’article date de 2016 et est encore plus d’actualité maintenant), le développement semble être un travail d’assemblage, qui consiste à écrire le moins de code possible, mais à utiliser un maximum de code écrit par d’autres personnes. Ce code externe peut être constitué de centaines, voire de milliers, de dépendances (et de sous-dépendances) ; certaines d’entre-elles sont plus des “snippets de code” que des vraies bibliothèques.
Le cas de left-pad est symptomatique. Ces 11 pauvres lignes de code, qui ne changeront pas, quel est le besoin d’aller les charger à l’extérieur à chaque déploiement ? Quelle est la complexité d’écrire ce code soi-même ? Ou, au pire, de le recopier dans notre base de code ?
Surtout que, d’après une étude de la société de sécurité Veracode, dans 79% des cas les bibliothèques tierces ne sont jamais mises à jour.
J’ai vu un projet Javascript qui importait l’ensemble du package country-flag-icons, juste pour afficher les drapeaux de la France, de l’Allemagne et de l’Italie. Le package pèse 6,5 MO, alors que les trois fichiers SVG pèsent en tout 910 octets. Même pas un kilo-octet ! Et on parle de drapeaux de pays, quelque chose qui n’évolue vraiment pas souvent. Donc plutôt que de retélécharger 6,5 MO à chaque fois qu’on prépare un déploiement, pourquoi ne pas simplement recopier les trois pauvres fichiers (et citer leurs auteurs correctement, comme on l’a toujours fait dans le logiciel libre) ?
N’allez pas croire que c’est un problème propre au monde Javascript. J’ai vu exactement les mêmes dérives sur des projets PHP et Python.
En PHP, j’ai vu plusieurs projets professionnels qui étaient bloqués sur une version obsolète du langage. Ces projets utilisaient tous Symfony, ainsi qu’une liste de dépendances longue comme le bras, chargées avec Composer. Sauf que pour passer à une version récente de PHP, il aurait fallu mettre à jour Symfony (ce qui peut être délicat si on part d’une version vraiment ancienne) ; mais pour mettre à jour Symfony, il faut mettre à jour toutes les autres dépendances ; malheureusement, plusieurs de ces bibliothèques ne sont pas compatibles avec des versions récentes de Symfony. Ça devient complètement kafkaïen. Le résultat, c’est que le plus simple était de ne pas mettre à jour…
J’ai vu un projet PHP qui utilisait l’ORM Doctrine, et qui chargeait trois différentes extensions à Doctrine. Évidemment, la plupart des capacités d’une extension se retrouvait dans les deux autres. Les développeurs ne savaient plus trop laquelle des trois était vraiment utilisée. Et évidemment, au moins une des trois n’était pas maintenue.
Quelle est la solution à tout ça ? Ce serait trop beau s’il y avait une solution miracle. Il faut prendre le temps de réfléchir et de se poser quelques questions avant d’ajouter une dépendance à un projet :
- Cette dépendance est-elle vraiment nécessaire ? Le gain de temps qu’elle va m’apporter à court terme vaut-il les futurs problèmes qu’elle pourrait générer ?
- Puis-je développer moi-même cette fonctionnalité, dans un temps raisonnable par rapport à sa valeur, et avec la qualité nécessaire ?
- Est-elle développée par un organisme, un groupe de développeurs, ou au moins un développeur reconnu par la communauté ?
De manière générale, c’est une bonne idée d’essayer de limiter les dépendances à l’essentiel.