Der Installationsschritt ist der gefährlichste Moment Deines Tages
Es ist ein Dienstagmorgen. Eine Entwicklerin installiert ein beliebtes open-source-Paket, das sie schon hundertmal genutzt hat. Nichts wirkt verdächtig: Der Fortschrittsbalken läuft durch, die Eingabeaufforderung kehrt zurück, sie macht weiter. Was sie nicht sehen kann: Die Version, die sie gerade geladen hat, ging vor vier Stunden online und in ihrem Installationsskript stecken ein paar Zeilen, die ihre SSH-Schlüssel und Umgebungsvariablen auslesen und an einen Server schicken, von dem sie noch nie gehört hat. Wenn die erste Warnung erscheint, sind die Schlüssel längst weg.
Das ist kein Gedankenspiel. Genau so funktionierte die TrapDoor-Kampagne im Mai 2026. Mehr als 34 bösartige Pakete tauchten fast gleichzeitig auf PyPI, npm und Crates.io auf, jedes darauf ausgelegt, in dem Moment bösartigen Code auszuführen, in dem es installiert oder importiert wurde.
Der Schaden entsteht bei der Installation, nicht zur Laufzeit
Die meisten stellen sich eine Schwachstelle als etwas vor, das später zubeißt, wenn die App in der Produktion läuft. Supply-Chain-Angriffe warten nicht so lange. Ein Post-Install-Skript, oder ein Paket, das beim Import Code ausführt, läuft mit den Rechten des Nutzers auf dem Rechner, der gerade installiert: einem Laptop, einem CI-Runner, einem Build-Server. Genau dort liegen die SSH-Schlüssel, die Cloud-Tokens und die .env-Dateien. Der Moment der Installation ist der Augenblick, in dem der Code des Angreifers und Deine Geheimnisse im selben Raum sind.
Warum „danach" zu spät ist
Dashboards für Schwachstellen und Audit-Berichte sind nützlich, aber sie schauen zurück. Sie sagen Dir, was bereits installiert ist. Ein Angreifer, der eine bösartige Version in ein beliebtes Paket schmuggelt, setzt genau auf diese Lücke: die Stunden oder Tage zwischen Veröffentlichung und Entdeckung, um so viele Rechner wie möglich zu erreichen. Bis ein Scanner die Version meldet, ist die Installation längst gelaufen.
Frisch veröffentlichte releases sind die scharfe Kante dieses Problems. Eine brandneue Version wurde am wenigsten geprüft, was sie zugleich am ehesten bösartig und am wenigsten wahrscheinlich bereits gemeldet macht. Das gefährlichste Paket an einem beliebigen Tag ist meistens das neueste.
Auf dem Build-Server ist es noch schlimmer
Ein Laptop ist eine Maschine. Ein CI-Runner ist eine Maschine, die alles berührt. Continuous-Integration-Pipelines installieren dependencies bei jedem Lauf frisch, meist mit weitreichenden Anmeldedaten direkt in der Umgebung: Deploy-Keys, Registry-Tokens, Cloud-Rollen. Ein bösartiges Post-Install-Skript auf einem CI-Runner kompromittiert nicht nur eine Entwicklerin. Es kann die Artefakte erreichen, die Du an alle weiter unten in der Kette auslieferst.
Und weil CI jedes Mal von Grund auf installiert, wird eine vergiftete Version in dem Moment gezogen, in dem sie veröffentlicht wird, automatisch, ohne dass ein Mensch dabei stutzig werden könnte. Bei der Installation ist die Gefahr auf dem Laptop groß und in der Pipeline geradezu kritisch. Genau dort verdient sich eine Prüfung ihren Platz, die vor der Installation läuft, immer auf dieselbe Weise.
Die Prüfung nach vorne ziehen
Ein gate vor der Installation ändert die Reihenfolge der Schritte. Bevor irgendetwas geschrieben oder ausgeführt wird, tut es Folgendes:
- Es löst auf, was der Paketmanager gleich installieren würde: jedes Paket und seine exakte Version, inklusive aller transitiven dependencies.
- Es prüft jedes davon gegen die öffentlichen Schwachstellen-Datenbanken: NIST NVD, OSV.dev und die GitHub Advisory Database.
- Es wendet einen freshness hold an. Jede release, die jünger als ein paar Tage ist, gilt als ungeprüft und wird zurückgehalten, denn genau in diesem Zeitfenster leben Supply-Chain-Angriffe.
- Es schließt im Zweifel ab (fail closed). Ist etwas als bösartig bekannt, verdächtig neu oder schlicht nicht überprüfbar, stoppt die Installation. Nichts wird geschrieben, nichts wird ausgeführt.
Der freshness hold, einfach erklärt
Warum neue releases überhaupt zurückhalten? Weil die Faktenlage einseitig ist. Eine Version, die seit Wochen öffentlich ist, wurde von Tausenden heruntergeladen, importiert und gelesen. Wäre sie bösartig, hätte es vermutlich jemand bemerkt. Eine Version, die heute Morgen online ging, hatte nichts davon. Der freshness hold sagt einfach: Lass sie die Menge erst ein paar Tage testen. Du verlierst fast nichts, denn die Version, die Du wirklich brauchst, ist ohnehin meist schon Tage oder Wochen alt. Und Du umgehst genau das Zeitfenster, auf das Angreifer angewiesen sind.
„Steht mir das nicht ständig im Weg?"
Eine berechtigte Sorge: Ein gate, das nervt, ist ein gate, das man abschaltet. Deshalb sind diese leise gebaut. Sie halten nur die neuesten releases zurück, nicht Deinen ganzen Dependency-Baum. Ergebnisse werden zwischengespeichert, sodass wiederholte Installationen nicht von Neuem gescannt werden. Und wenn eine Registry oder Datenbank nicht erreichbar ist, schließt das gate ab, statt Dinge durchzuwinken. Du merkst es nicht, bis zu dem Tag, an dem es etwas stoppt, dem einzigen Tag, an dem es zählt.
„Ich pinne meine Versionen. Reicht das nicht?"
Pinning und lockfiles sind gute Hygiene, aber sie lösen ein anderes Problem. Ein lockfile garantiert, dass alle im Projekt dieselben Versionen installieren. Es schützt Dich vor Drift, nicht vor einer schlechten Version, die Du überhaupt erst pinnst. In dem Moment, in dem Du eine dependency hinzufügst oder anhebst, löst Du selbst eine frische Version auf und schreibst sie ins lockfile. Ist das die vergiftete Version, pinnt das lockfile den Angriff brav fest und liefert ihn ans ganze Team aus.
Ein gate vor der Installation sitzt einen Schritt davor. Es prüft die Version in dem Moment, in dem Du sie hinzufügen würdest, bevor sie überhaupt ins lockfile gelangt. Beide arbeiten zusammen: Das gate entscheidet, ob eine Version sicher genug zum Pinnen ist. Das lockfile hält dann alle auf der Version, die das gate bereits freigegeben hat.
Einschalten
Der Sinn eines gates ist, dass es standardmäßig an ist. Das Einschalten sollte also eine einmalige Sache sein, keine Gewohnheit. Jedes 5bats-gate installiert sich als dünner Wrapper vor den Paketmanager, den Du ohnehin benutzt. Du installierst es einmal und von da an wird jede Installation aufgelöst und geprüft, bevor sie läuft. Kein Flag, das man sich merken muss, kein separater Befehl. Von da an ist das gate unsichtbar, bis zu dem Tag, an dem es etwas stoppt. Es gibt nichts, was Du in jedes Projekt einbauen müsstest, kein Dashboard zu beobachten und keine Entscheidung pro Installation. Genau das ist der Punkt: Das sicherste Verhalten ist das, was passiert, egal ob jemand daran denkt, danach zu fragen.
Im Zweifel abschließen, langweilig bleiben
Sicherheits-Tools gewinnen Vertrauen, indem sie berechenbar sind. Ein 5bats-gate, das etwas nicht überprüfen kann, verweigert es, jedes Mal, ohne Überraschungen und ohne Konfiguration. Langweiliger, standardmäßig aktiver Schutz schlägt cleveren Schutz, der erst eingerichtet werden will.
Dasselbe gate gibt es für die Paketmanager, die am ehesten in Deinem Alltag vorkommen: pip , Composer und Homebrew . Jedes macht den sichersten Moment, vor der Installation, zur Voreinstellung, ohne einen einzigen zusätzlichen Schritt, den man sich merken muss.
