Was ist npm?

Der Paketmanager für Node.JS

Definition

npm (Node Package Manager) ist der standardmäßige Paketmanager für die weit verbreiteten Programmiersprachen JavaScript und TypeScript. Es handelt sich dabei um eines der größten Online-Software-Register der Welt für öffentliche und private Codepakete. Gleichzeitig stellt npm ein Kommandozeilen-Tool (CLI) bereit, mit dem Entwickler auf dieses Registry zugreifen und so den gesamten Prozess rund um das Auffinden, Installieren, Verwalten, Aktualisieren und Veröffentlichen von Projektabhängigkeiten automatisieren können.

Überblick über npm

npm ist im Grunde ein System mit zwei Bestandteilen: ein umfangreiches Online-Registry und ein clientseitiges Kommandozeilen-Tool. Es automatisiert die Verwaltung wiederverwendbarer Codemodule und ist sowohl für die Open-Source-Zusammenarbeit als auch für die Entwicklung im Unternehmenskontext unverzichtbar.

Die Hauptfunktionen von npm umfassen die Automatisierung des Paket-Lebenszyklus. Mit dem Befehl npm install werden Abhängigkeiten aufgelöst und Pakete heruntergeladen, während npm publish neue oder aktualisierte Pakete in das Registry hochlädt. Das Tool verwaltet Versionsstände zur Sicherstellung der Kompatibilität von Abhängigkeiten und speichert Paketinformationen in der Datei package.json des jeweiligen Projekts.

Erste Schritte mit dem npm-Registry und der CLI

Das öffentliche npm-Registry dient als zentrale Distributionsplattform für das JavaScript- und TypeScript-Ökosystem, während die npm-CLI als direkter Zugangspunkt für Entwickler zur Verwaltung dieser Pakete fungiert.

Das am häufigsten genutzte öffentliche Registry ist: https://www.npmjs.com/

Node.js und der CLI-Client

Da npm standardmäßig mit Node.js (der JavaScript-Laufzeitumgebung) gebündelt ist, wird bei der Installation von Node.js automatisch auch der npm-CLI-Client mitinstalliert. Nach der Installation können Entwickler direkt auf Pakete aus dem Registry zugreifen und diese verwalten. Erste Schritte und Details zur Konfiguration finden Sie unter „Get Started with npm“.

Installation und Konfiguration

Die Installation erfolgt in der Regel durch das Herunterladen und Ausführen des Node.js-Installers für das jeweilige Betriebssystem – die npm-CLI ist dabei bereits enthalten. Nach erfolgreicher Installation steht die CLI direkt über die Kommandozeile zur Verfügung. Standardmäßig lädt die CLI Pakete aus dem öffentlichen Repository von npmjs. Wenn eine private oder selbstgehostete Registry verwendet werden soll, muss die Konfigurationsdatei .npmrc angepasst werden – mit der richtigen Registry-URL und den entsprechenden Authentifizierungsdaten. Auf dieselbe Weise verbindet sich die npm-CLI auch mit JFrog Artifactory über .npmrc.

Erstellen und Verwalten der package.json

package.json ist die zentrale Manifestdatei eines jeden Node.js-Projekts. Sie enthält Metadaten wie den Projektnamen, die Version, eine Beschreibung, den Haupteinstiegspunkt – und vor allem alle benötigten Abhängigkeiten. Eine saubere Verwaltung dieser Datei ist entscheidend für die Portabilität eines Projekts und dafür, dass es zuverlässig in unterschiedlichen Umgebungen reproduziert werden kann.

Grundlagen des Abhängigkeitsmanagements

Ein effektives Management von Abhängigkeiten ist die Basis für eine skalierbare JavaScript-Entwicklung. npm bietet dabei eine feingranulare Steuerung darüber, wie ein Projekt externe Codemodule verfolgt und verwendet.

Abhängigkeitsarten

In der Datei package.json werden Abhängigkeiten je nach Rolle im Projektlebenszyklus kategorisiert:

  • dependencies: Pakete, die für den produktiven Betrieb der Anwendung erforderlich sind.
  • devDependencies: Pakete, die ausschließlich für lokale Entwicklung, Tests und Build-Prozesse benötigt werden – z. B. Test-Runner oder Linter.
  • peerDependencies: Abhängigkeiten, die vom Konsumenten der Anwendung bereits vorhanden sein müssen. Typisch für Plugins oder Erweiterungen.
  • optionalDependencies: Pakete, die die Anwendung verwendet, wenn sie vorhanden sind – deren Fehlen führt jedoch nicht zu einem Installationsfehler.

Semantische Versionierung (SemVer)

Semantische Versionierung (SemVer) basiert auf einem dreiteiligen Versionsschema (MAJOR.MINOR.PATCH) und definiert klare Regeln, wie Versionen in Abhängigkeit von den vorgenommenen Änderungen erhöht werden:

  • MAJOR-Version: Nicht abwärtskompatible Änderungen an der API
  • MINOR-Version: Neue Funktionen, die abwärtskompatibel sind
  • PATCH-Version: Abwärtskompatible Fehlerbehebungen

In der package.json verwendet npm Präfixe wie ^1.0.4 oder ~1.0.4, um gültige Versionsbereiche gemäß den SemVer-Regeln festzulegen.

Overrides und Konfliktlösung

Abhängigkeitskonflikte treten häufig auf, wenn Pakete inkompatible SemVer-Bereiche angeben – was zu einer komplexen oder instabilen Abhängigkeitsstruktur führen kann. Das Feld overrides in der package.json ermöglicht es, explizit bestimmte Paketversionen im gesamten Abhängigkeitsgraphen zu erzwingen und damit potenziell problematische Sub-Abhängigkeiten zu überschreiben. So erhalten Entwickler eine feingranulare Kontrolle zur Konfliktlösung und zur Behebung von Sicherheitslücken in tief verschachtelten Abhängigkeiten.

Die Datei package-lock.json ist essentiell für deterministische Builds. Sie dokumentiert die exakte Abhängigkeitsstruktur zum Zeitpunkt der letzten erfolgreichen Installation – einschließlich Versionen, Bezugsquellen und Subresource Integrity (SRI)-Hashes aller Pakete (auch transitiver Abhängigkeiten), unabhängig von den Versionsangaben in der package.json.

Wenn ein anderer Nutzer oder ein CI/CD-Prozess später npm install ausführt, sorgt die package-lock.json dafür, dass exakt diese Versionen installiert werden. Dadurch wird die Versionsauflösung umgangen und typische Abhängigkeitsprobleme bei großen Projekten mit vielen Paketkonflikten wirksam reduziert.

So erstellen und veröffentlichen Sie npm-Pakete

Ein JavaScript-Paket besteht in der Regel aus einem Verzeichnis mit einer package.json-Datei. Um dieses Paket für andere verfügbar zu machen, sind eine sorgfältige Vorbereitung und die Veröffentlichung in einem Registry erforderlich.

Vorbereitung eines Pakets für die Verteilung

Die Vorbereitung stellt sicher, dass das Paket korrekt strukturiert und einsatzbereit ist. Dazu gehören die Definition der Haupteinstiegspunkte, der unterstützten Laufzeitumgebungen sowie aller notwendigen Metadaten. Ein gut vorbereitetes Paket kommuniziert klar seinen Zweck, seine Abhängigkeiten und Einschränkungen – und erleichtert so die Wiederverwendung durch andere Entwickler.

Das Einrichten wichtiger Dateien

Wichtige Dateien für die Verteilung sind:

  • README.md – dokumentiert Zweck und Nutzung
  • LICENSE – legt die rechtlichen Bedingungen für die Wiederverwendung fest
  • CHANGELOG – beschreibt die Versionshistorie und wesentliche Änderungen

Wesentliche Metadaten wie die SemVer-Version und Angaben zum Autor werden in der package.json definiert.

Versionierung und Veröffentlichung von Paketen

Die Paketversionierung muss den Regeln der semantischen Versionierung (SemVer) folgen. Mit dem Befehl npm version lassen sich Versionsnummern bequem aktualisieren – inklusive automatischer Anpassung der package.json und Erstellung eines entsprechenden Git-Tags.

Der eigentliche Release erfolgt durch den Befehl npm publish, nachdem die neue Version getaggt und committet wurde.

Was sind die größten Sicherheitsrisiken bei npm?

Der Node Package Manager (npm) ist ein zentraler Baustein der JavaScript-Entwicklung – und damit ein bevorzugtes Ziel für Angriffe auf die Anwendungssicherheit (AppSec), insbesondere in Form komplexer Supply-Chain-Attacken. Die größten Sicherheitsrisiken ergeben sich aus dem enormen Umfang des Registrys und dem hohen Maß an Vertrauen, das Entwickler in Pakete setzen.

Die Absicherung von JavaScript-Abhängigkeiten innerhalb der Software-Lieferkette ist eine kritische Herausforderung im Bereich AppSec. Die gängigen Angriffsvektoren nutzen Schwachstellen oder eingeschleusten Schadcode im Rahmen des Paketnutzungsmodells aus.

Zentrale Sicherheitsrisiken bei npm:

1.  Account-Übernahmen und Package-Poisoning-Angriffe

Angreifer übernehmen gezielt die Konten vertrauenswürdiger Paket-Maintainer – häufig durch ausgeklügelte Phishing-Attacken, die selbst 2FA-Schutzmechanismen umgehen. Anschließend injizieren sie bösartigen Code in beliebte und weit verbreitete Bibliotheken. Diese direkte Manipulation der Softwarequelle ist eine gravierende Supply-Chain-Attacke, die sofort alle nachgelagerten Nutzer kompromittiert.

Ein aktuelles Beispiel aus dem September 2025 gilt als der bislang größte Angriff in der Geschichte von npm: Durch die Kompromittierung eines Maintainer-Kontos konnte Schadcode in Bibliotheken wie debug und chalk eingeschleust werden. Kurz darauf infizierte der sogenannte „Shai-Hulud“-Wurm über 500 weitere Pakete, indem er sich selbst replizierte, Zugangsdaten wie npm- und Cloud-Tokens stahl und automatisiert schadhafte Versionen unter den übernommenen Accounts veröffentlichte.

Diese Vorfälle verdeutlichen die enorme Bedrohung durch kompromittierte Entwicklerzugänge und automatisierte Schadfunktionen – und unterstreichen die Notwendigkeit strenger Sicherheitsprüfungen und Schutzmaßnahmen entlang der gesamten Software-Lieferkette.

2. Aufblähung von Abhängigkeiten und transitive Risiken

Die durchschnittliche moderne Anwendung basiert auf Hunderten oder sogar Tausenden transitiver Abhängigkeiten – also Paketen, die von den explizit installierten Paketen eingebunden werden. Eine Schwachstelle oder ein bösartiger Code in einer einzigen dieser tief verschachtelten Abhängigkeiten wird automatisch während des Build-Prozesses ausgeführt und schafft dadurch eine riesige, intransparente Angriffsfläche. Entwickler haben in der Regel keine ausreichende Sichtbarkeit in diesen tiefen Abhängigkeitsgraphen, was eine manuelle Risikobewertung nahezu unmöglich macht.

3. Bösartige Run-Skripte und Postinstall-Hooks

npm-Pakete können Skripte enthalten, die während des Installationsvorgangs automatisch ausgeführt werden – insbesondere über sogenannte Lifecycle-Hooks wie postinstall. Angreifer nutzen diese legitime Funktion gezielt aus, um beliebigen Code auszuführen, sobald ein Entwickler npm install aufruft. Dies kann dazu führen, dass Umgebungsvariablen ausgelesen, Zugangsdaten gestohlen oder Malware installiert wird. Da der Code mit den Rechten des Entwicklers auf dessen lokaler Maschine läuft, eröffnen sich potenziell Wege für eine laterale Ausbreitung im Unternehmensnetzwerk.

4. Typosquatting und Dependency Confusion

Beim Typosquatting veröffentlichen Angreifer Pakete mit Namen, die bekannten Bibliotheken täuschend ähnlich sehen (z. B. react-domm statt react-dom). Ziel ist es, dass Entwickler versehentlich das falsche Paket installieren und damit kompromittiert werden.

Dependency Confusion wiederum nutzt Schwachstellen in der internen Paketverwaltung von Organisationen aus: Angreifer registrieren ein öffentliches Paket mit dem gleichen Namen wie ein intern genutztes privates Paket. Wenn Entwickler oder automatisierte Build-Systeme die Abhängigkeit auflösen, kann fälschlicherweise die öffentliche – und möglicherweise bösartige – Version installiert werden. Das führt zu schwerwiegenden Sicherheitsvorfällen in der Lieferkette.

 

Best Practices für den Einsatz von npm

Die Umsetzung bewährter Best Practices reduziert Sicherheitsrisiken, verbessert die Zusammenarbeit und erhöht die Zuverlässigkeit von Node.js-Anwendungen über den gesamten Softwareentwicklungszyklus (SDLC) hinweg.

Abhängigkeiten effektiv verwalten

Die Verwaltung von Abhängigkeiten ist kein passiver Prozess – es erfordert aktive Maßnahmen und geeignete Tools. Teams sollten unbedingt Lockfiles wie package-lock.json nutzen, um deterministische Builds zu erzwingen und die potenzielle Angriffsfläche durch transitive Abhängigkeiten zu minimieren. Darüber hinaus sollte eine automatisierte Software Composition Analysis (SCA) möglichst früh in den Entwicklungsprozess integriert werden – idealerweise bereits beim Hinzufügen eines Pakets. So lassen sich bekannte Schwachstellen und Lizenzverstöße erkennen, bevor problematische Pakete überhaupt in die Anwendung gelangen.

npm-Skripte zur Automatisierung nutzen

Das Feld scripts in der package.json sollte als zentrale Stelle genutzt werden, um Build-, Test- und Entwicklungsaufgaben im Projekt zu standardisieren. Diese Konsistenz ist ein grundlegendes Prinzip von DevOps. Durch einheitliche Kommandos stellen Entwickler sicher, dass wiederkehrende Aufgaben in allen Umgebungen – von lokalen Rechnern bis hin zu Continuous-Integration-Servern – zuverlässig und nachvollziehbar ausgeführt werden.

Pakete aktuell und sicher halten

Regelmäßige Updates von Paketen sind essentiell für die Sicherheit – denn neue Versionen enthalten häufig Patches für bekannte Schwachstellen. Gleichzeitig müssen Updates kontrolliert erfolgen, um unerwartete wesentliche Veränderungen zu vermeiden. Teams sollten Updates automatisieren, jedoch nur innerhalb sicherer SemVer-Grenzen, und Sicherheits-Gates in ihre Pipelines integrieren. So wird sichergestellt, dass neu installierte Abhängigkeiten keine Schwachstellen mit hoher Kritikalität in das Projekt einführen.

Wie lässt sich JFrog mit npm integrieren?

Die JFrog Plattform bietet eine leistungsstarke, zentrale Lösung zur sicheren und effizienten Verwaltung und Verteilung von npm-Paketen über die gesamte Entwicklungspipeline hinweg. Sie bringt unternehmensweite Kontrolle in das JavaScript-Ökosystem durch umfassende Integration mit npm-Repositories.

Im Zentrum der JFrog Plattform steht JFrog Artifactory, ein universelles Artefakt-Repository für Software. Es dient als zentrale Quelle für alle Binärartefakte – einschließlich npm-Paketen – und bildet damit die Grundlage für moderne DevOps-Praktiken. Diese zentrale Verwaltung ermöglicht eine durchgängige Automatisierung und steigert die Effizienz und Geschwindigkeit von CI/CD-Prozessen erheblich.

JFrog Curation begegnet den Sicherheitsrisiken des riesigen öffentlichen npm-Registrys direkt durch eine automatisierte Vorabprüfung von Open-Source-Paketen auf Schwachstellen, Malware und Lizenzverstöße, und zwar bevor diese Pakete auf Entwicklerrechner geladen oder in Builds integriert werden. Durch ein kontextbasiertes Sicherheitsmodell filtert JFrog potenziell schadhafte oder nicht konforme Pakete und blockiert deren Verwendung in Ihre Umgebung. So lassen sich Bedrohungen wie Package Poisoning, Typosquatting und die Ausnutzung transitiver Abhängigkeiten effektiv eindämmen. Ein anschauliches Beispiel dafür ist der „Manifest Confusion“-Angriff auf npm: JFrog Artifactory schützt lokale Repositories, indem es Pakete basierend auf ihrer tatsächlichen package.json-Information indexiert und speichert – und nicht auf Grundlage manipulierter Metadaten-Dateien.

Durch die Kombination von Artifactorys Artefaktmanagement mit den erweiterten Sicherheitsfunktionen der JFrog Platform wird das unsichere öffentliche npm-Ökosystem in eine verlässliche und konforme Software-Lieferkette verwandelt.

Mit der JFrog Plattform können Sie Open-Source-Komponenten proaktiv verwalten und absichern und Ihre JavaScript-Lieferkette gezielt vor den neuesten npm-Angriffen schützen. Probieren Sie es aus: in einer Online-Tour, einer persönlichen Demo oder mit einer kostenlosen Testversion von JFrog Curation.

Mehr zum Thema DevOps

JFrog Artifactory

Eine End-to-End-DevOps-Plattform zur Verwaltung, Sicherung und Nachverfolgung aller Artefakte, Binärdateien, Pakete, Dateien, Container und Komponenten in der Software-Lieferkette.

JFrog Artifactory entdecken

JFrog Xray

Unsere universelle Software Composition Analysis-Lösung, für die proaktive Identifizierung von Schwachstellen.

JFrog Xray entdecken

JFrog ML

Erstellen Sie ein einheitliches Single System of Record für ML-Modelle, das Ihre KI-Entwicklung mit Ihrem bestehenden SDLC zusammen bringt.

JFrog ML entdecken

Release Fast Or Die