Wichtigste Erkenntnisse
- RequireJS ist ein archiviertes OpenJS-Projekt, daher ist kein Upstream-Betreuer dazu verpflichtet, zukünftige Sicherheitslücken zu beheben.
- Die Umstellung auf ES-Module betrifft Moduldefinitionen, das Ladeverhalten, die Build-Optimierung, das Testen und die Bereitstellung.
- CVE-2024-38999 wird je nach Quelle mit einem Schweregrad zwischen „mittel“ und „kritisch“ eingestuft, daher ist die Erreichbarkeit von größerer Bedeutung.
- Bei Magento und Moodle ist RequireJS in die Plattform integriert, sodass der Verzicht auf AMD ein projektbezogener Schritt auf Plattformebene ist.
RequireJS hat dazu beigetragen, dass große Browseranwendungen modular aufgebaut wurden, noch bevor es native ES-Module gab. Die aktive Entwicklung wurde bereits vor Jahren eingestellt, was an sich nichts Besonderes wäre – wäre da nicht die Tatsache, dass AMD-Loader nach wie vor die Grundlage für einen Großteil des Frontend-Codes in Unternehmen bilden, oft auf Plattformen, auf denen man den Loader nicht einfach austauschen kann.
In diesem Beitrag geht es darum, was das „End of Life“ für einen Loader wie RequireJS bedeutet, wie man mit einer wichtigen CVE-Schwachstelle umgeht, deren Schweregrade stark voneinander abweichen, und warum die Abkehr von AMD eher ein Architekturprojekt als eine einfache Aktualisierung der Abhängigkeiten ist.
RequireJS hat das Problem des modularen JavaScripts gelöst, noch bevor der Browser dies tat
Irgendwo in Ihrem Unternehmen gibt es wahrscheinlich ein Frontend, das immer noch über ein data-main Attribut, und niemand aus dem aktuellen Team hat es geschrieben. Es wird seit etwa einem Jahrzehnt problemlos geladen, und genau das ist das Problem.
RequireJS kam auf den Markt, als Browser noch keine native Möglichkeit hatten, JavaScript in Module aufzuteilen und diese bei Bedarf abzurufen. Es implementierte AMD, das „Asynchronous Module Definition“-Format, sodass große Codebasen Abhängigkeiten explizit deklarieren und parallel laden konnten, anstatt alles zu einer einzigen Datei zusammenzufügen und darauf zu hoffen, dass die Reihenfolge stimmte. Für Teams, die im Jahr 2013 Hunderttausende von Zeilen an den Browser übermittelten, machte diese Struktur den Unterschied zwischen einer wartbaren App und einem Sumpf aus globalen Variablen aus.
Man findet es immer noch an bestimmten Stellen. In einem Magento-2-Shop. In einer Moodle-Installation. In einer Backbone- oder Knockout-Anwendung aus dem Jahr 2015. In einem internen Berichtstool, das mit data-main das niemand mehr geöffnet hat, seit derjenige, der es gebaut hat, weggegangen ist.
Es ist nichts kaputt, niemand kümmert sich aktiv um die Wartung, und die zugrunde liegende Architektur lässt keine kleine, gezielte Korrektur zu. Eine architektonische Entscheidung lässt sich nicht einfach durch einen Patch beheben.
Wird RequireJS noch weiterentwickelt?
Auf keinen Fall sollte man darauf einen Support-Plan aufbauen, und die Bezeichnung ist offiziell. Die OpenJS Foundation führt RequireJS als archiviertes Projekt auf, zusammen mit anderen Bibliotheken, deren Lebenszyklus beendet ist, wie jQuery Mobile, jQuery UI, Sizzle und dem Pointer Events Polyfill.
Das Repository ist nach wie vor öffentlich zugänglich und das npm-Paket lässt sich weiterhin installieren, doch der Status „Archiviert“ gibt Ihnen keinen Anlass zu der Annahme, dass jemand aus dem Upstream-Bereich reagieren wird, wenn der nächste Sicherheitshinweis erscheint.
Wussten Sie schon: RequireJS veröffentlichte am 30. November 2025 die Version 2.3.8 – mehr als fünf Jahre, nachdem OpenJS das Projekt erstmals auf seine End-of-Life-Liste gesetzt hatte. Diese Einstufung bedeutet also nicht, dass der Code eingefroren ist. Es bedeutet lediglich, dass sich niemand zur Weiterentwicklung verpflichtet hat, und das ist etwas ganz anderes.
AMD hat das Problem des Ladens von Browser-Modulen gelöst, noch bevor die Plattform eine Lösung parat hatte, und native ES-Module sowie moderne Bundler haben schließlich die gesamte Aufgabe übernommen, für die das Projekt ursprünglich entwickelt wurde. Das Projekt wurde sogar öffentlich aufgefordert, auf seiner eigenen Startseite seinen Status anzugeben. Auf dieser Seite wird nach wie vor 2.3.7 als aktuellste Version angegeben, und es wird nichts über die Kennzeichnung „Archiviert“ erwähnt.
Ein CVE mit drei verschiedenen Schweregraden lesen
38999 ist der Befund, der bei RequireJS-Scans auftritt. Es handelt sich um einen „Prototype Pollution“-Fehler in s.contexts._.configure das alle Versionen bis einschließlich 2.3.6 betrifft und dessen Behebung in Version 2.3.7 im Juli 2024 bereitgestellt wurde.
Schauen Sie sich nun an, wie die Datenbanken denselben Fehler bewerten.
| Quelle | CVSS | Schweregrad |
|---|---|---|
| NVD (NIST) | Keine Bewertung vergeben | Nicht angereichert |
| CISA-ADP | 10,0 (v3.1) | Kritisch |
| Haltbar | 9.3 (v4.0) | Kritisch |
| GitHub-Hinweis | 8.9 (v4.0) | Hoch |
| Snyk | 6.9 (v4.0) | Mittel |
Die Differenz erscheint enorm, ist jedoch größtenteils auf die Bewertungsmechanismen zurückzuführen und nicht auf tatsächliche Meinungsverschiedenheiten bezüglich des Fehlers. Die Bewertung von CISA-ADP mit 10,0 basiert auf CVSS v3.1. Die Bewertung von Tenable (9,3) und GitHub (8,9) basieren auf denselben CVSS v4.0-Basismetriken, wobei der niedrigere Wert von GitHub darauf zurückzuführen ist, dass die Bedrohungsmetrik „Exploit Maturity“ auf dem Level „Proof-of-Concept“ (E:P) angesetzt wurde. Der eigentliche Ausreißer ist die Bewertung „Medium“ von Snyk, die auf einer deutlich niedrigeren Auswirkungsbewertung beruht.
Der EPSS-Wert des CVE liegt bei etwa 0,76 Prozent (0,0076 auf einer Skala von 0 bis 1, Stand: 14. September 2026), sodass das Modell die Wahrscheinlichkeit einer Ausnutzung in den nächsten 30 Tagen auf unter ein Prozent schätzt. Es rangiert zwar immer noch im Mittelfeld aller bewerteten CVEs (53. Perzentil), doch dieses Perzentil ist eine Einstufung im Vergleich zu anderen CVEs und keine Wahrscheinlichkeit.
Ein Teil des Problems liegt in der Art und Weise, wie der Eintrag behandelt wurde. Das NVD listet CVE-2024-38999 nach wie vor als „Deferred“ (zurückgestellt) auf, sodass jede nachgelagerte Datenbank ihre eigenen Bewertungsgrundlagen auf einen Eintrag anwandte, den das NVD nie analysiert hat. RequireJS erhielt im gleichen Zeitraum außerdem einen zweiten Bericht über Prototyp-Pollution. Dieser, CVE-2024-38998, betraf die „config“-Funktion und wurde im Januar 2025 abgelehnt, nachdem der zuständige CNA zu dem Schluss gekommen war, dass es sich nicht um ein Sicherheitsproblem handelte.
Bei der Triage ist der Score nur eine Eingangsgröße, und die Erreichbarkeit sollte stärker gewichtet werden als die Zahl. Können vom Angreifer kontrollierte Daten das Objekt erreichen, das Ihre Anwendung an requirejs.config()? Dieser Ruf ist es, der s.contexts._.configure. Falls die Antwort „nein“ lautet, ist das praktische Risiko unabhängig von der Farbe des Abzeichens gering.
Achtung: Eine angefochtene Bewertung führt nicht dazu, dass der Befund aus Ihrem Bericht entfernt wird. „Wir halten diese Bewertung für überbewertet“ ist eine Meinung, keine Korrekturmaßnahme.
In der Praxis gilt: Wenn die CVE in Ihrem Bericht aufgeführt ist und Sie nicht auf eine behobene Version umsteigen können, benötigen Sie entweder einen gepatchten Build oder eine schriftliche Erklärung zur Ausnutzbarkeit. Eine Auseinandersetzung über den CVSS-Wert zählt als keines von beiden.
Die Wahl einer RequireJS-Alternative ist eine architektonische Entscheidung
RequireJS durch etwas Neueres zu ersetzen, klingt nach einer Änderung der Abhängigkeiten. Es geht dabei eher darum, zu entscheiden, wie Ihre Anwendung Code überhaupt lädt.
Es gibt vier realistische Ziele, die nicht gleichwertig sind. Native ES-Module überlassen das Laden dem Browser oder der Laufzeitumgebung, und RequireJS verschwindet vollständig. Von einem Bundler verwaltete Module übergeben den Modulgraphen an Webpack, Vite oder esbuild, die ihn zur Build-Zeit auflösen und eine optimierte Ausgabe liefern. Inkrementelle Adapter und Interop-Shims ermöglichen die Koexistenz von AMD- und ES-Modulen während einer langwierigen Migration. Und das Laden einfacher Skripte ist in einigen älteren oder stark eingeschränkten Umgebungen nach wie vor eine echte Anforderung.
Hinter all diesen vier Punkten verbirgt sich eine Frage, die man leicht übersehen könnte: Benötigt die Anwendung noch das Laden von Laufzeitmodulen, oder war das lediglich eine Einschränkung der Zeit, in der sie entwickelt wurde? Ein Großteil der AMD-Architektur existiert einzig und allein deshalb, weil die Browser von 2013 keine Alternative boten.
Hinzu kommen die im Code selbst verankerten Annahmen, und genau hier gehen die Schätzungen schief. Rechnen Sie damit, dass benannte und anonyme Moduldefinitionen im selben Baum vermischt sind, sowie Plugin-Präfixe wie text! zum Laden von Vorlagen und Aliasen, die in pathsund shim Einträge für globale Variablen, die nicht von AMD stammen. Rechnen Sie mit zirkulären Abhängigkeiten, die der Loader zufällig toleriert, mit globalen Variablen, die als Module verpackt sind, um modular zu wirken, ohne es tatsächlich zu sein, sowie mit einer Optimierer-Konfiguration, die bereitstellungsspezifische Bundles erzeugt.
Insider-Tipp: Suche in der Codebasis nach text!, shimund paths bevor man überhaupt mit der Planung beginnt. Diese drei Muster lassen sich besser als Indikatoren für Migrationsprobleme heranziehen als die reine Anzahl der Dateien, da jedes einzelne das Laufzeitverhalten widerspiegelt, das ein Bundler nicht ohne Weiteres reproduzieren kann.
Legen Sie das Ziel fest, bevor jemand mit dem Code anfängt. Die Umstellung auf ES-Module und die Nachbildung der Struktur der Optimierer-Artefakte sind unterschiedliche Projekte mit unterschiedlichen Budgets.
Warum automatisierte Konvertierung nur ein Teil der Lösung ist
Codemods und jscodeshift-Transformationen gibt es wirklich, und sie verschieben die Syntax. Bei einfachen statischen Modulen ist ein define([...], function(){}) Der Block wird zu import Aussagen ohne großes Aufhebens. Das Problem ist, dass die Syntax nie der schwierige Teil war.
Laufzeitannahmen lassen sich nicht transformieren. Die Ladereihenfolge und Nebeneffekte können sich ändern, sobald Module anders aufgelöst werden, und eine App, die sich auf eine bestimmte AMD-Ladereihenfolge verlassen hat, kann auf eine Weise ausfallen, die durch statische Analysen nicht erkannt wird. Tests sind oft direkt an die RequireJS-Konfiguration gekoppelt, sodass sie aus Gründen fehlschlagen, die nichts mit dem zu testenden Code zu tun haben. Produktionsumgebungen erwarten möglicherweise ein bestimmtes, optimiertes Artefakt-Layout, das ein neuer Bundler einfach nicht erzeugt. Und dynamische Modulnamen – also solche, die zur Laufzeit aus Variablen zusammengesetzt werden – entziehen sich per Definition der statischen Analyse.
Dann gibt es noch die Plattformfalle, in der genau eine Magento- oder Moodle-Installation steckt. Auf diesen Plattformen ist RequireJS Teil der Frontend-Architektur. In der Regel lässt sich die Konfiguration erweitern (Magento-Module und -Themes enthalten ihre eigenen requirejs-config.js (z. B. Dateien), doch der Austausch des Ladeprogramms selbst ist durch die Möglichkeiten der jeweiligen Plattformversion begrenzt.
Aus der Praxis: Stellen Sie sich einen Online-Händler vor, der eine stark angepasste Magento-Installation mit rund 30 benutzerdefinierten RequireJS-Modulen und einem Theme nutzt, das Teile der Loader-Konfiguration der Plattform überschreibt. Ein Plattform-Upgrade bringt zwar möglicherweise eine neuere RequireJS-Version mit sich, doch die Shop-Oberfläche startet danach weiterhin über AMD. Der Ausstieg aus RequireJS hängt in diesem Fall ebenso sehr von der Roadmap der Plattform wie von Ihrer eigenen ab, und kein Codemod kann hier Abhilfe schaffen.
Beginnen Sie also vor jeder Schätzung mit einer Zählübung. Zählen Sie die Dateien. Zählen Sie die Shim-Einträge. Finden Sie heraus, welcher Teil der Loader-Konfiguration von Ihnen stammt und welcher Teil zur Plattform gehört. Diese drei Antworten bestimmen fast alles, was danach folgt, und die letzte entscheidet darüber, ob eine Migration überhaupt in Ihrer Hand liegt.
Ein schrittweiser Übergang von AMD zu modernen Modulen
Wenn eine Migration ansteht, ist eine schrittweise Umsetzung fast immer besser als eine komplette Neuprogrammierung auf einen Schlag. Die Reihenfolge, die sich in der Produktion in der Regel bewährt, beginnt mit der Erfassung des Modulgraphen, damit Sie wissen, was von was abhängt. Von dort aus sollten Sie zunächst Blattmodule und andere Bereiche mit geringem Risiko umstellen und Kompatibilitätsschichten gezielt einführen, anstatt dies erst dann zu tun, wenn etwas nicht mehr funktioniert. Passen Sie die Tests parallel zu den Produktionsmodulen an, die sie abdecken, und nicht erst im Nachhinein. Messen Sie nach jeder Phase die Bundle-Größe und das Ladeverhalten und entfernen Sie Shims erst, nachdem alle Verbraucher dieser Shims entfernt wurden.
Nach jeder Phase sollte die App bereit zur Veröffentlichung sein. Der Sinn der „Leaf-First“-Reihenfolge besteht darin, dass ein Modul mit geringem Risiko sauber rückgängig gemacht werden kann, falls sich das Ladeverhalten ändert – was bei einem Modul mit tiefgreifenden Abhängigkeiten nicht möglich ist.
Profi-Tipp: Sofern es die Architektur zulässt, sollten Sie während der Umstellung den alten RequireJS-Build und den neuen Bundler-Build parallel hinter einem Feature-Flag ausführen und die Netzwerk-Wasserfall-Diagramme der beiden Versionen vergleichen, bevor Sie den alten Loader entfernen. Eine geänderte Reihenfolge der Anfragen ist oft der erste Hinweis darauf, dass sich ein Nebeneffekt verschoben hat.
Allerdings gehört nicht jede Anwendung in diesen Pfad. Die richtige Vorgehensweise hängt davon ab, wer für den Build verantwortlich ist und wie „eingefroren“ das Artefakt ist. Bei einer kleinen Codebasis und voller Kontrolle über den Build sollten Sie auf ES-Module umstellen und die Sache damit erledigen. Wenn die Plattform für den Loader verantwortlich ist, sollten Sie vor Ort einen Patch anwenden und das Plattform-Upgrade in eine zeitlich festgelegte Roadmap aufnehmen. Bei einem „eingefrorenen“ Artefakt oder Anforderungen mit Air-Gap sollten Sie vor Ort einen Patch anwenden und die Ausnutzbarkeit für den Prüfer dokumentieren.
Wenn der vorhandene Loader weiterhin geschützt werden muss
Manchmal steht die Migration in diesem Quartal nicht auf der Tagesordnung, und der Loader muss in der Zwischenzeit dennoch sicher funktionieren. Dies ist häufig bei langlebigen Unternehmensportalen, eingebetteten Verwaltungskonsolen und Produkten mit festgelegten Upgrade-Fenstern der Fall. Es tritt auch bei Anwendungen auf, die ersetzt statt modernisiert werden, sowie bei Systemen, deren Regressionstests eine Loader-Migration noch nicht unterstützen können.
Seien Sie sich über die Obergrenze im Klaren. Ein Update auf 2.3.7 oder die aktuelle Version 2.3.8 behebt CVE-2024-38999, aber weiter geht es mit dem Upstream nicht. Nichts deutet auf eine Version 2.4 hin. Hinter dem nächsten Sicherheitshinweis steht keine Verpflichtung zur Wartung, und es gibt keine garantierte Reaktionszeit, falls ein solcher veröffentlicht wird.
Realitätscheck: Ein Upgrade auf die neueste RequireJS-Version bedeutet nicht automatisch, dass die Software unterstützt wird. Eine heute behobene Schwachstelle sagt nichts darüber aus, ob im nächsten Jahr eine neue Schwachstelle gemeldet wird.
Der „Endless Lifecycle Support“ (ELS) von TuxCare für RequireJS umfasst die Versionen 2.1.22 und 2.3.6, die als npm-Pakete aus dem von TuxCare gehosteten Repository bereitgestellt werden – einschließlich SBOM- und VEX-Dokumenten sowie auf den CVSS-Schweregrad abgestimmter Reaktionsziele. Dabei handelt es sich eher um Verwaltungsarbeit als um Upstream-Entwicklung. Das Team prüft, ob jede neue CVE für die abgedeckten Versionen relevant ist, portiert den Fix zurück und testet jeden Build vor der Veröffentlichung auf Integrität, Funktionalität und Regressionen, damit bestehender Code weiterhin so funktioniert wie bisher. Dieser letzte Aspekt ist besonders wichtig für einen Loader, bei dem man es sich nicht leisten kann, dass er sich anders verhält. Dies ist ein Teil des umfassenderen EOL-Bibliothekssupports von TuxCare für Teams, die an Komponenten festhalten, deren Upstream-Entwicklung bereits weitergegangen ist.
Nachhaltigkeit von OpenJS nach Abschluss der aktiven Phase eines Projekts
Dass RequireJS ein archiviertes OpenJS-Projekt ist, bedeutet nicht das Ende seiner Sicherheitsgeschichte. Das „Ecosystem Sustainability Program“ der Stiftung wurde genau zu diesem Zweck ins Leben gerufen: Damit archivierte, EOL- und ältere Versionen kommerzielle Sicherheitsdienste erhalten können, wobei ein Teil der Einnahmen an die Stiftung und ihre Projekte zurückfließt. TuxCare ist Gold-Mitglied und Anbieter in diesem Programm, und seine Patches werden nachgelagert bereitgestellt. Sie werden nicht zu Upstream-Releases von RequireJS.
Betrachten Sie RequireJS also als Teil der Architektur, die das Frontend zusammenhält, denn genau das ist es. Es an einem Freitagnachmittag einfach zu löschen, wird nicht gut ausgehen, und sein Ersatz verdient mehr als nur einen hastigen Paketwechsel.
