Fin de vie de RequireJS : risques liés au chargeur AMD et prise en charge de la sécurité

Les correctifs php2shell (CVE-2026-109618 et CVE-2026-109619) pour les versions de PHP en fin de vie sont désormais disponibles. Les réponses du service commercial étant plus lentes que d'habitude en raison d'une forte demande, le moyen le plus rapide d'obtenir les paquets corrigés est d'acheter ELS for Runtimes en ligne (s'ouvre dans un nouvel onglet). Consulter la FAQ sur les correctifs

Accédez directement au résumé généré par l'IA de cet article de blog

  • Résumez cet article avec Perplexity
  • Résume cet article avec Gemini

Principaux enseignements

  • RequireJS est un projet archivé d'OpenJS ; par conséquent, aucun responsable en amont ne s'engage à corriger les futures vulnérabilités.
  • Le passage aux modules ES a des répercussions sur les définitions de modules, le comportement de chargement, l'optimisation de la compilation, les tests et le déploiement.
  • La vulnérabilité CVE-2024-38999 est classée entre « moyenne » et « critique » selon les sources ; c'est donc l'accessibilité qui prime.
  • Sur Magento et Moodle, RequireJS est intégré à la plateforme ; par conséquent, l'abandon d'AMD relève d'un projet au niveau de la plateforme.

RequireJS a permis de modulariser les applications web volumineuses bien avant l'apparition des modules ES natifs. Son développement actif a pris fin il y a plusieurs années, ce qui n'aurait rien d'exceptionnel si ce n'est que les chargeurs AMD sont toujours utilisés dans de nombreux codes front-end d'entreprise, souvent sur des plateformes où il n'est pas possible de remplacer ce chargeur par un autre.

Cet article explique ce que signifie la « fin de vie » pour un chargeur tel que RequireJS, comment gérer une vulnérabilité CVE majeure dont les niveaux de gravité varient considérablement, et pourquoi l'abandon d'AMD relève davantage d'un projet d'architecture que d'une simple mise à jour des dépendances.

RequireJS a résolu le problème de la modularité du JavaScript avant même que les navigateurs ne le fassent

Il y a sans doute, quelque part dans votre entreprise, une interface utilisateur qui démarre encore via un data-main attribut, et personne dans l'équipe actuelle ne l'a écrit. Il s'est chargé sans problème pendant près d'une décennie, et c'est justement là le problème.

RequireJS a vu le jour à une époque où les navigateurs ne disposaient d’aucun moyen natif de diviser le JavaScript en modules et de les charger à la demande. Il a implémenté le format AMD (Asynchronous Module Definition), permettant ainsi aux bases de code volumineuses de déclarer explicitement leurs dépendances et de les charger en parallèle, au lieu de tout concaténer dans un seul fichier en espérant que l’ordre soit respecté. Pour les équipes qui déployaient des centaines de milliers de lignes de code sur les navigateurs en 2013, cette structure faisait la différence entre une application facile à maintenir et un marécage de variables globales.

On en trouve encore à certains endroits. Une boutique en ligne Magento 2. Un déploiement Moodle. Une application Backbone ou Knockout datant de 2015. Un outil de reporting interne intégré à data-main que personne n'a ouvert depuis le départ de celui qui l'a construit.

Rien n'est défectueux, personne ne s'en occupe activement, et l'architecture sous-jacente ne permet pas d'apporter une correction ponctuelle et ciblée. On ne peut pas contourner une décision architecturale à coups de correctifs.

RequireJS fait-il encore l'objet d'une maintenance ?

Ce n'est en aucun cas une base sur laquelle on souhaiterait construire un plan de support, et cette mention est officielle. La Fondation OpenJS classe RequireJS parmi les projets « archivés », aux côtés d'autres bibliothèques en fin de vie telles que jQuery Mobile, jQuery UI, Sizzle et le polyfill Pointer Events.

Le dépôt reste public et le paquet npm s'installe toujours, mais le statut « Archivé » ne vous donne aucune raison de vous attendre à ce que les responsables en amont réagissent lorsque le prochain avis de sécurité sera publié.

Le saviez-vous ? RequireJS a publié la version 2.3.8 le 30 novembre 2025, plus de cinq ans après qu’OpenJS l’ait inscrit pour la première fois sur sa liste des logiciels en fin de vie. Ce statut ne signifie donc pas que le code est figé. Cela signifie simplement que personne ne s’est engagé à le maintenir, ce qui est tout à fait différent.

AMD a résolu le problème du chargement des modules de navigateur avant même que la plateforme n’ait trouvé de solution, et les modules ES natifs, associés aux outils de regroupement modernes, ont fini par prendre entièrement le relais de la tâche pour laquelle ce projet avait été conçu. Le projet a même été invité publiquement à préciser son statut sur sa propre page d’accueil. Cette page indique toujours la version 2.3.7 comme étant la dernière en date et ne fait aucune mention de la mention « Archivé ».

Lecture d'une vulnérabilité CVE présentant trois niveaux de gravité différents

38999 C'est le résultat qui apparaît lors des analyses effectuées par RequireJS. Il s'agit d'un bug de « pollution des prototypes » dans s.contexts._.configure qui concerne toutes les versions jusqu'à la 2.3.6, et dont le correctif a été intégré à la version 2.3.7 en juillet 2024.

Voyez maintenant comment les bases de données évaluent ce même bug.

Source CVSS Sévérité
NVD (NIST) Aucune note attribuée Non enrichi
CISA-ADP 10,0 (v3.1) Critique
Tenable 9.3 (v4.0) Critique
Avis de GitHub 8,9 (v4.0) Haut
Snyk 6.9 (v4.0) Moyen

L'écart semble énorme, mais il s'explique en grande partie par les mécanismes de notation plutôt que par un véritable désaccord sur le bug lui-même. La note de 10,0 attribuée par CISA-ADP correspond à la version 3.1 du CVSS. La note de 9,3 attribuée par Tenable et celle de 8,9 attribuée par GitHub reposent sur les mêmes indicateurs de base du CVSS v4.0 ; la note inférieure de GitHub s'explique par l'ajout de l'indicateur de menace « Exploit Maturity » au niveau « Proof-of-Concept » (E:P). La véritable valeur aberrante est la note « Medium » attribuée par Snyk, qui repose sur une évaluation de l'impact nettement inférieure.

Le score EPSS de cette CVE est d’environ 0,76 % (0,0076 sur une échelle de 0 à 1, au 14 septembre 2026) ; le modèle estime donc que la probabilité d’exploitation au cours des 30 prochains jours est inférieure à 1 %. Il se classe toujours en milieu de tableau parmi tous les CVE notés (53e centile), mais ce centile correspond à un classement par rapport aux autres CVE, et non à une probabilité.

Une partie du problème tient à la manière dont cet enregistrement a été géré. Le NVD classe toujours le CVE-2024-38999 comme « différé » ; ainsi, chaque base de données en aval a appliqué ses propres critères de notation à un enregistrement que le NVD n’a jamais analysé. RequireJS a également reçu un deuxième rapport de pollution de prototype au cours de la même période. Celui-ci, CVE-2024-38998, concernait la fonction `config` et a été rejeté en janvier 2025 après que son analyseur de vulnérabilité (CNA) eut conclu qu’il ne s’agissait pas d’un problème de sécurité.

Pour le triage, le score n’est qu’un critère parmi d’autres, et l’accessibilité mérite d’être davantage prise en compte que le chiffre lui-même. Les données contrôlées par un attaquant peuvent-elles atteindre l’objet que votre application transmet à requirejs.config()? C'est cet appel qui alimente s.contexts._.configure. Si la réponse est non, le risque concret est faible, quelle que soit la couleur du badge.

Attention : une note contestée ne supprime pas le résultat de votre rapport. « Nous pensons que celle-ci est surévaluée » est une opinion, pas une mesure corrective.

Concrètement, si la vulnérabilité CVE figure dans votre rapport et que vous ne pouvez pas passer à une version corrigée, vous devez disposer soit d’une version corrigée, soit d’une déclaration écrite attestant de la possibilité d’exploitation de la vulnérabilité. Un argument relatif au score CVSS ne saurait être considéré comme l’un ou l’autre.

Le choix d'une alternative à RequireJS relève d'une décision architecturale

Remplacer RequireJS par une solution plus récente semble impliquer un changement de dépendances. Cela revient en fait à déterminer la manière dont votre application charge le code.

Il existe quatre destinations possibles, et elles ne sont pas équivalentes. Les modules ES natifs laissent le navigateur ou le runtime se charger du chargement, et RequireJS disparaît complètement. Les modules gérés par un bundler transmettent le graphe de modules à webpack, Vite ou esbuild, qui le résolvent au moment de la compilation et fournissent un résultat optimisé. Les adaptateurs incrémentiels et les shims d'interopérabilité permettent aux modules AMD et ES de coexister pendant une migration de longue durée. Et le chargement de scripts simples reste une nécessité réelle dans certains environnements plus anciens ou verrouillés.

Derrière ces quatre points se cache une question qu’on a tendance à négliger. L’application a-t-elle encore besoin du chargement de modules à l’exécution, ou s’agissait-il d’une contrainte liée à l’époque où elle a été développée ? Une grande partie de l’architecture AMD existe simplement parce que les navigateurs de 2013 n’offraient pas d’autre solution.

Il y a ensuite les hypothèses intégrées au code lui-même, et c'est là que les estimations s'avèrent erronées. Attendez-vous à ce que des définitions de modules nommés et anonymes se côtoient dans la même arborescence, ainsi qu'à des préfixes de plugins tels que text! pour charger les modèles et les alias définis dans paths, et shim entrées pour les variables globales non AMD. Attendez-vous à des dépendances circulaires que le chargeur a par hasard tolérées, à des variables globales encapsulées sous forme de modules pour donner l'impression d'être modulaires sans l'être réellement, ainsi qu'à une configuration de l'optimiseur qui génère des bundles spécifiques au déploiement.

Conseil d'initié : Rechercher dans le code source les éléments suivants : text!, shim, et paths avant de définir le périmètre d’une quelconque analyse. Ces trois modèles permettent de mieux anticiper les difficultés liées à la migration que le simple nombre de fichiers, car chacun d’entre eux reflète un comportement d’exécution qu’un outil de regroupement ne peut pas reproduire automatiquement.

Choisissez la destination avant même de toucher au code. La conversion vers les modules ES et la reproduction d'une structure d'artefacts générée par l'optimiseur sont deux projets distincts, avec des budgets différents.

Pourquoi la conversion automatisée n'est qu'une solution partielle

Les « codemods » et les transformations « jscodeshift » existent bel et bien, et ils modifient effectivement la syntaxe. Pour les modules statiques simples, un define([...], function(){}) le bloc devient import des instructions sans trop de complications. Le problème, c'est que la syntaxe n'a jamais été la partie la plus difficile.

Les hypothèses d’exécution ne se transforment pas. L’ordre de chargement et les effets secondaires peuvent changer dès lors que les modules sont résolus différemment, et une application qui s’appuyait sur une séquence de chargement AMD spécifique peut présenter des dysfonctionnements que l’analyse statique ne détecte pas. Les tests sont souvent directement liés à la configuration de RequireJS ; ils échouent donc pour des raisons sans rapport avec le code testé. Les déploiements en production peuvent s’attendre à une structure d’artefacts optimisée particulière qu’un nouvel outil de regroupement ne produit tout simplement pas. Et les noms de modules dynamiques, ceux assemblés à partir de variables lors de l’exécution, échappent par définition à l’analyse statique.

Il y a ensuite le « piège de la plateforme », qui concerne précisément les déploiements Magento ou Moodle. Sur ces plateformes, RequireJS fait partie intégrante de l’architecture front-end. Il est généralement possible d’étendre sa configuration (les modules et thèmes Magento intègrent leurs propres requirejs-config.js (les fichiers, par exemple), mais le remplacement du chargeur lui-même est limité par les capacités prises en charge par la version de la plateforme.

Sur le terrain : imaginez un e-commerçant utilisant une installation Magento fortement personnalisée, avec une trentaine de modules RequireJS personnalisés et un thème qui remplace certaines parties de la configuration du chargeur de la plateforme. Une mise à jour de la plateforme peut apporter une nouvelle version de RequireJS intégrée, mais la boutique continue malgré tout à démarrer via AMD. Dans ce cas, l’abandon de RequireJS dépend autant de la feuille de route de la plateforme que de la vôtre, et aucun outil de modification de code ne peut y remédier.

Commencez donc par un exercice de comptage avant toute estimation. Comptez les fichiers. Comptez les entrées « shim ». Déterminez quelle partie de la configuration du chargeur vous appartient et quelle partie relève de la plateforme. Ces trois réponses déterminent la quasi-totalité des étapes en aval, et la dernière permet de savoir si la migration relève même de votre contrôle.

Une transition progressive des processeurs AMD vers les modules modernes

Lorsqu’une migration est envisagée, une mise en place progressive est presque toujours préférable à une refonte radicale. La démarche qui fait généralement ses preuves en production commence par la cartographie du graphe des modules, afin de déterminer les dépendances entre eux. À partir de là, convertissez d’abord les modules « feuille » et autres limites à faible risque, et introduisez des couches de compatibilité de manière délibérée plutôt que par accident, lorsque quelque chose cesse de fonctionner. Convertissez les tests en même temps que les modules de production qu’ils couvrent, et non après coup. Mesurez la taille des bundles et leur comportement de chargement après chaque étape, et ne supprimez les shims qu’une fois que tous leurs utilisateurs ont été supprimés.

À l'issue de chaque étape, l'application doit être prête à être déployée. L'intérêt de l'ordre « leaf-first » réside dans le fait qu'un module à faible risque peut être annulé proprement si le comportement de chargement venait à changer, ce qui n'est pas possible pour un module faisant l'objet de dépendances profondes.

Conseil de pro : lorsque l’architecture le permet, exécutez en parallèle l’ancienne version de RequireJS et la nouvelle version du bundler derrière un indicateur de fonctionnalité pendant la conversion, puis comparez les graphiques en cascade des requêtes réseau entre les deux avant de supprimer l’ancien chargeur. Un changement dans l’ordre des requêtes est souvent le premier indice qu’un effet secondaire a été déplacé.

Cependant, toutes les applications ne se prêtent pas à cette approche. La bonne décision dépend de qui est responsable de la compilation et du degré de « gel » de l’artefact. Si la base de code est petite et que vous maîtrisez entièrement la compilation, passez aux modules ES et n’y pensez plus. Lorsque le chargeur appartient à la plateforme, appliquez un correctif sur place et inscrivez la mise à niveau de la plateforme dans une feuille de route à date fixe. Pour un artefact « gelé » ou des exigences impliquant un environnement isolé, appliquez un correctif sur place et documentez les vulnérabilités exploitables à l’intention de l’auditeur.

Lorsque le chargeur existant a encore besoin d'être protégé

Il arrive parfois que la migration ne soit pas prévue pour ce trimestre, mais que le chargeur doive néanmoins rester sécurisé en attendant. C'est souvent le cas dans les portails d'entreprise à longue durée de vie, les consoles d'administration intégrées et les produits soumis à des fenêtres de mise à niveau contrôlées. Cela se produit également dans les applications qui sont remplacées plutôt que modernisées, ainsi que dans les systèmes dont la couverture des tests de régression ne permet pas encore de prendre en charge la migration du chargeur.

Soyez lucide quant à la limite. Passer à la version 2.3.7 ou à la version actuelle 2.3.8 permet de corriger la vulnérabilité CVE-2024-38999, mais c’est tout ce que vous permettra d’obtenir la version en amont. Rien n’indique qu’une version 2.4 soit prévue. Il n’y a aucun engagement de maintenance associé au prochain avis de sécurité, ni aucun délai de réponse garanti si un tel avis venait à être publié.

Retour à la réalité : passer à la dernière version de RequireJS ne signifie pas pour autant que le logiciel bénéficie d'un support technique. Une version corrigée aujourd'hui ne garantit en rien qu'il n'y aura pas de faille signalée l'année prochaine.

Le service « Endless Lifecycle Support » (ELS) de TuxCare pour RequireJS couvre les versions 2.1.22 et 2.3.6, fournies sous forme de paquets npm à partir du registre hébergé par TuxCare, avec des documents SBOM et VEX ainsi que des objectifs de réponse liés au niveau de gravité CVSS. Il s'agit d'un travail de gestion plutôt que de développement en amont. L’équipe vérifie si chaque nouvelle vulnérabilité CVE s’applique aux versions couvertes, rétroporte le correctif et teste chaque version quant à son intégrité, ses fonctionnalités et l’absence de régressions avant sa mise en production, afin que le code existant continue de fonctionner comme aujourd’hui. Ce dernier point est essentiel pour un chargeur dont le comportement ne doit en aucun cas changer. Il s’agit d’un élément du support plus large proposé par TuxCare pour les bibliothèques en fin de vie (EOL), destiné aux équipes qui restent bloquées sur des composants dont le développement en amont a évolué.

Pérennité d'OpenJS après la phase active d'un projet

Le fait que RequireJS soit un projet archivé d’OpenJS ne signifie pas pour autant la fin de son parcours en matière de sécurité. Le programme « Ecosystem Sustainability » de la Fondation a justement été mis en place pour permettre aux versions archivées, en fin de vie (EOL) et plus anciennes de bénéficier de services de sécurité commerciaux, une partie des recettes étant reversée à la Fondation et à ses projets. TuxCare est membre « Gold » et prestataire au sein de ce programme, et ses correctifs sont intégrés en aval. Ils ne sont pas intégrés aux versions en amont de RequireJS.

Considérez donc RequireJS comme un élément à part entière de l’architecture qui assure la cohésion du front-end, car c’est bien ce qu’il est. Le supprimer un vendredi après-midi ne se passera pas bien, et son remplacement mérite mieux qu’un simple changement de bibliothèque effectué à la va-vite.

Résumé
Fin de vie de RequireJS : risques liés au chargeur AMD et prise en charge de la sécurité
Nom de l'article
Fin de vie de RequireJS : risques liés au chargeur AMD et prise en charge de la sécurité
Description
RequireJS est un projet archivé d'OpenJS pour lequel aucune maintenance n'est assurée. Découvrez ce que signifie la fin de vie (EOL) pour les front-ends AMD et les options d'assistance qui s'offrent à vous.
Auteur
Nom de l'éditeur
de TuxCare
Logo de l'éditeur

Rejoignez plus de 4 500 professionnels de Linux et de l'Open Source!

2 fois par mois. Pas de spam.

Table des matières
Obtenez les réponses à vos questions sur la sécurité des logiciels libres

Rejoignez plus de 4 500 professionnels de Linux et de l'Open Source!

2 fois par mois. Pas de spam.