Zum Hauptinhalt springen

Wormbox: Sandbox und Audit für Developer-Toolchains

Inhaltsverzeichnis

Drei npm-Vorfälle in sechs Monaten, jedes Mal eine andere Angriffstechnik, jedes Mal mit echtem Schaden. Wormbox soll ein Versuch sein, solchen Angriffen auf Prozessebene zu begegnen. Das Tool ist ein Sandbox- und Audit-Layer um Developer-Toolchains. Version 0.1.0 (Beta) deckt zunächst die Node.js-Familie ab (node, npm, npx, pnpm, yarn, bun); das Konzept lässt sich nach und nach auf weitere CLI-Familien wie Terraform, gh, kubectl, gcloud sowie AI-Tools wie claude, codex oder aider erweitern. Vorerst macOS only.

brew tap head1328/wormbox \
  https://codeberg.org/head1328/homebrew-wormbox.git
brew install wormbox
Dreimal dasselbe npm install eines synthetischen insecure-utility-Pakets, dessen postinstall-Skript AWS_ACCESS_KEY_ID und AWS_SECRET_ACCESS_KEY aus der Shell-Umgebung liest und ausgibt. Ohne aktive wormbox-Shim landen beide Werte beim Skript (rot). Mit aktiver Shim filtert die Env-Allowlist beide vorher weg (grün, undefined). Mit WORMBOX_EXTRA_ENV="AWS_ACCESS_KEY_ID" wird die Allowlist nur für genau diesen einen Aufruf um genau diese eine Variable erweitert; AWS_SECRET_ACCESS_KEY bleibt blockiert.

Was passiert ist
#

chalk/debug, September 2025. Per Phishing erbeutete Maintainer-Tokens, ein Wallet-Hijacker als Payload. chalk@5.6.1 und benachbarte Pakete bekamen ein dist/index.js, das window.ethereum und window.fetch überschrieb. Die betroffenen Pakete kommen zusammen auf über zwei Milliarden Downloads pro Woche.

Shai-Hulud 2.0, November 2025. Ein selbstreplizierender Wurm. Postinstall-Hooks stahlen den npm-Token des Opfers, der Wurm veröffentlichte damit weitere Pakete und arbeitete sich so durch das Ökosystem.

Axios, März 2026. Die Versionen 1.14.1 und 0.30.4 brachten einen plattformübergreifenden RAT (Remote Access Trojan) mit, der z. B. process.env.AWS_* oder GITHUB_TOKEN aus der Umgebung las und per HTTP an einen Command-and-Control-Server schickte. Ohne Install-Hook, alles zur Laufzeit.

Was soll schon schiefgehen? npm install holt Code von hunderten Maintainern, die du nie getroffen hast, und du führst ihn lokal aus - zusammen mit deinen Tokens, deinen Credentials und Zugriff auf dein gesamtes Filesystem.

Der Ansatz
#

Hardening gegen Supply-Chain-Angriffe hat zwei Ebenen.

Auf der spezifischen Ebene stehen Signaturen, Pattern-Matches und Heuristiken für bekannte Muster. Hilfreich, weil sofort einsetzbar. Aber leicht zu umgehen, und sie hinkt jedem neuen Angriff hinterher.

Auf der generischen Ebene stehen Defaults. Was darf ein Prozess überhaupt? Welche Umgebungsvariablen sieht er? Welche Dateien? Wer hier deny-default fährt, blockiert ganze Klassen von Angriffen unabhängig vom konkreten Angriffsmuster.

Wormbox baut primär auf die generische Ebene. In 0.1.0 (Beta) tragen die spezifischen Checks aber noch einen relevanten Teil mit - sie fangen Muster ab, für die es noch keine generische Strategie gibt.

Ziel der nächsten Version: mehr Angriffsklassen generisch abdecken.

Wie es funktioniert
#

Bei der Installation legt wormbox unter ~/.wormbox/shims einen Shim für jedes unterstützte Tool an und stellt das Verzeichnis an den Anfang des PATH. Wer also npm install aufruft, trifft auf den Shim, nicht das Original.

Der Shim macht drei Dinge in dieser Reihenfolge:

  1. Er findet das echte Binary auf dem System.
  2. Er startet ein Audit-Preflight (Go-Binary), das vor der Installation einen Blick auf das Paket wirft.
  3. Er übergibt an das echte Tool - verpackt in sandbox-exec mit deny-default SBPL-Profil, in einer per env -i reduzierten Umgebung.

Auf einem TTY gibt der Shim direkt vor Schritt 3 eine einzeilige Statuszeile auf stderr aus, damit klar ist, welcher Aufruf gerade gewrappt wird (▪ wormbox · npm install). WORMBOX_QUIET=1 schaltet die Zeile komplett ab, NO_COLOR=1 nur die Farbe.

Audit-Preflight
#

Vor npm install läuft eine statische Prüfung gegen das Paket:

  • Hat das Paket Lifecycle-Hooks (preinstall, install, postinstall)?
  • Auffällige Code-Patterns: curl | sh, child_process, Base64-Blobs, Token-Strings?
  • Wie alt ist die Version? Unter 24 Stunden ist nicht zwangsläufig verdächtig, aber einen Hinweis wert - die Bewertung liegt beim User.
  • Existiert eine Provenance-Attestation?
  • Browser-Hooks wie window.ethereum oder window.fetch?

Trifft eines davon, gibt es eine Warnung mit Schweregrad und je nach Kritikalität einen Abbruch. Die Schwellen und Pattern-Sets sind aktuell fest im Code; das wandert demnächst in eine Konfigdatei.

Jedes Finding trägt eine stabile Kennung der Form WB-<KATEGORIE>-<NNN> (PAT für Code-Patterns, BRW für Browser-Injection, LIF für Lifecycle-Hooks, AGE für Paketalter, PRV für Provenance, TAR für Tarball-Ebene). Der vollständige Katalog liegt in der CODES.md im Repo.

Sandbox via sandbox-exec
#

Das eigentliche Tool läuft unter sandbox-exec mit einem Deny-Default-Profil im SBPL-Dialekt. Lesen ist nur im Projektverzeichnis erlaubt. Zusätzlich explizit gesperrt:

  • ~/.aws, ~/.ssh
  • ~/.config/{gh,gcloud}, ~/.kube, ~/.docker
  • ~/.npmrc
  • ~/Library/Keychains plus die üblichen Pfade von Passwort-Managern und Cookie-Stores

Env-Allowlist
#

Direkt vor dem exec räumt der Shim die gesamte Umgebung weg (env -i) und reicht nur weiter, was auf einer Allowlist steht: POSIX-Basics, Node-Variablen, Proxies, CI-Signale, NPM_TOKEN. Nicht weitergereicht werden insbesondere AWS_*, GITHUB_TOKEN, GH_TOKEN, GOOGLE_*, AZURE_*, OPENAI_*, ANTHROPIC_* und KUBECONFIG. Pro Projekt lassen sich Allow- und Denylist über ~/.config/wormbox/config.json anpassen.

Wie wormbox bei den drei Vorfällen abschneidet
#

VorfallAuditSandboxEnv-Allowlist
chalk/debugVoll: Pattern, Alter, Provenancen/an/a
Shai-Hulud 2.0Teil: postinstall, PatternsGreift bei ~/.aws, ~/.sshLücke: NPM_TOKEN ist auf der Allowlist, wegen npm publish
AxiosSchwach: nur Alter und ProvenanceGreift bei den Credential-PfadenGreift: AWS_* und GITHUB_TOKEN erreichen das Paket nicht

Drei sehr unterschiedliche Angriffsszenarien. Genau deswegen braucht es mehr als eine Schicht.

Kein Ersatz für Container
#

Container und VMs sind die übliche Antwort auf “Code, dem ich nicht traue”. Sie isolieren - aber:

  • Den lokalen Toolstack komplett in Container zu verlagern ist im Alltag keine Option - keiner baut für jeden npm-Aufruf einen Container-Alias.
  • Sie isolieren nur, wenn man sie passend konfiguriert. docker run -e AWS_* reicht Credentials durch - und im Container kann jedes Package sie abgreifen.
  • Die Isolation endet an der Container-Grenze. Tokens und Credentials, die im Container liegen, kann ein npm install von dort ohne Weiteres abgreifen.

Wormbox sichert den einzelnen Prozess, der Container nur die Umgebung drumherum.

Was 0.1 nicht kann
#

Damit klar ist, was das Tool (noch) nicht leistet:

  • Nur macOS. Linux via bubblewrap oder Landlock wäre denkbar.
  • Nur die Node-Toolchain. terraform, vault, helm, gh, kubectl, gcloud sind Kandidaten für die nächste Version.
  • Pure-Runtime-Payload ohne erkennbares Pattern bleibt riskant. Ohne Install-Hook und ohne bekannte Signatur findet das Audit keinen Ansatzpunkt - dann bleibt nur die Sandbox als Auffangnetz.
  • sandbox-exec ist seit Jahren als deprecated markiert und wird trotzdem in jedem macOS-Release weiter ausgeliefert. Solange das so bleibt, baut wormbox darauf auf. Was kommt, wenn Apple es irgendwann wirklich entfernt, ist offen - das Endpoint Security Framework wäre eine Option, deckt aber nicht 1:1 ab, was sandbox-exec heute leistet.

Ausblick
#

  • Weitere Tool-Familien neben Node.
  • Mehr Konfigurierbarkeit. Die aktuell hartkodierten Checks sollen konfigurierbar werden.
  • Hintergrund-Daemon. Heute läuft jeder Aufruf isoliert. Ein langlebiger Daemon ermöglicht warmen Audit-Cache (spürbar schnellere wiederholte Installs), Korrelation über Aufruf-Grenzen hinweg (Worm-artige Muster, die ein einzelner Aufruf nicht sehen kann) und persistente Trust-Entscheidungen pro Projekt.
  • Kontinuierliches Audit. Aktuell nur vor der Installation, geplant auch laufende Checks danach. Setzt auf dem Daemon auf.
  • Signierter Pattern-Feed. Neue Audit-Patterns sollen ohne neues Release nachladbar sein, damit auf akute Vorfälle binnen Stunden reagiert werden kann.

Lizenz
#

MIT. Beiträge, Issues und Forks willkommen.


Hat dir das hier geholfen?
Unterstütze gerne via: