So blockierst Du anfällige oder bösartige PHP-Pakete vor dem „Composer install“

Du hast vor Monaten die Website eines Kunden erstellt. Sie funktioniert, ist schon eine Weile online, und Du hast ihre dependencies seit dem Start nicht mehr angerührt. Heute gibt es eine kleine Änderung, die Du veröffentlichen musst – eine kleine Anpassung am Text, eine neue Vorlage –, also machst Du ein Commit und pushst. Irgendwo in Deiner Pipeline läuft composer install. Es fügt nichts Neues hinzu; es installiert einfach genau die Versionen neu, die bereits im Projekt hinterlegt sind – dieselben, die schon seit Monaten dort sind. Routine. Der Deploy ist erfolgreich. Du machst weiter.

In diesem langweiligen, grünen Schritt verbirgt sich das stille Problem. Ein PHP-Projekt speichert seine dependencies in einer Datei namens composer.lock – einer festgeschriebenen Liste mit den genauen Versionen aller verwendeten Pakete, sowohl der von Dir ausgewählten als auch der rund hundert, von denen jedes einzelne wiederum abhängt. Am Tag der Erstellung war alles sauber. Aber „sauber“ hat nur eine begrenzte Haltbarkeit. Wochen später kann in einer dieser festgelegten Versionen eine Schwachstelle entdeckt werden, oder das Konto eines maintainers kann gehackt werden und eine manipulierte release unter einer Nummer herausgeschleust werden, der Du bereits vertraust. Von diesem Moment an installiert jedes composer install getreulich die nun gefährliche Version neu – und Composer führt den eigenen Setup-Code dieses Pakets als Teil der Installation aus, bevor irgendjemand die Chance hatte, einen Blick darauf zu werfen.

Das ist keine hypothetische Situation. Im Mai 2026 haben Angreifer mithilfe der gestohlenen Zugangsdaten eines maintainers innerhalb weniger Minuten bösartige Releases in rund 700 Versionen des weit verbreiteten Laravel-Lang-Pakets eingeschleust – Code, der über die Post-Install-Hooks von Composer sofort nach der Installation ausgeführt wurde. Jedes Projekt, das in diesem Zeitfenster zufällig composer install ausführte, war kompromittiert, noch bevor ein Mensch die Nachricht überhaupt lesen konnte.

Composer hat hier inzwischen wirksame Schutzmaßnahmen eingebaut: Neuere Versionen blockieren standardmäßig bekannte Sicherheitswarnungen und Malware, wenn Du Pakete hinzufügst oder aktualisierst, und composer audit meldet Probleme im Nachhinein. Aber eine bestimmte Hintertür bleibt offen – die Neuinstallation einer bereits gesperrten Version, die erst nach ihrer Sperrung gefährlich wurde. composer-cve-gate wurde entwickelt, um genau diese Hintertür zu schließen.

Das Problem, ganz einfach ausgedrückt

Die meisten Leute stellen sich den riskanten Moment so vor, dass man ein neues Paket hinzufügt. Bei PHP ist es aber genauso oft genau das Gegenteil: die Installation, die Du bei jedem einzelnen Deploy ausführst – aus einer lockfile, die Du seit Monaten nicht mehr geändert hast. Composer-Code kann bereits während der Installation selbst ausgeführt werden – beim Autoload-Bootstrap oder beim Laden eines composer-plugin-Pakets –, sodass eine fehlerhafte Version bereits während der Installation läuft, lange bevor composer audit (das erst im Nachhinein prüft) an die Reihe kommt.

Die Blockierung durch Native Composer hilft, wenn Du Abhängigkeiten änderst, aber sie bewertet eine Version, die zum damaligen Zeitpunkt bereits in Deiner Lockdatei stand und „clean“ war, nicht neu. Das ist die Lücke bei der Installation anhand der Lockdatei: „clean-at-commit“ ist nicht dasselbe wie „clean-at-deploy“, und die Lücke dazwischen kann Wochen betragen.

Wem passiert das schon?

Agenturen und Freiberufler, die Websites neu bereitstellen, die sie vor langer Zeit erstellt haben; jedes Team, dessen CI bei jedem Push composer install anzeigt; der maintainer, der vor einem Jahr ein lockfile fixiert hat und davon ausgeht, dass „Ich habe nichts geändert“ bedeutet, dass „sich nichts geändert hat“. Die Pakete haben sich nicht verändert – aber das Wissen der Welt über sie schon.

Was „composer-cve-gate“ macht – und wie es funktioniert

composer-cve-gate ist ein Composer-Plugin. Es fügt drei Befehle hinzu – safe-install, safe-upgrade und safe-scan – und, was am wichtigsten ist, es kann den einfachen Befehl composer install gateen, der über Deine lockfile ausgeführt wird.

Wie composer-cve-gate ein bösartiges Paket beim Install blockiertEin composer install aus dem Lockfile wird vom Gate abgefangen. Es prüft jedes Paket im Lockfile über fünf Signale, bevor ein Post-Install-Script läuft, und blockiert ein markiertes.composer installführt Scripts beim Install auscomposer-cve-gate5 Signale + Freshness,aus dem LockfileBlockiertbevor Scripts laufen
Das Lockfile wird geprüft, bevor composer install läuft — ein markiertes Paket erreicht Dein Projekt nie.

Damit wird die Lücke bei der Installation aus dem Sperrmodus geschlossen

Das ist der eigentliche Grund, warum es dieses Tool gibt. Wenn das Gate auf den Blockiermodus umgeschaltet ist, liest ein einfaches composer install die lockfiles, überprüft jedes gesperrte Paket und bricht den Vorgang ab, bevor ein Download oder ein Skript nach der Installation ausgeführt wird, falls eines davon markiert ist – und erfasst damit genau den Fall, den die native Composer-Richtlinie übersieht: eine Version, die zum Zeitpunkt des Commits noch in Ordnung war, zum Zeitpunkt der Bereitstellung jedoch bereits gefährlich ist.

Fünf unabhängige Signale, direkt abgefragt

Jedes Paket – und sein transitiver Baum – wird anhand der OSV-Datenbank, der GitHub Advisory Database und des NIST NVD auf bekannte Schwachstellen überprüft, zusätzlich wird das OpenSSF-Register für bösartige Pakete nach bestätigter Malware durchsucht. composer-cve-gate fragt diese Feeds selbst ab, anstatt sich auf eine einzige Quelle zu verlassen, sodass eine Lücke in einer Quelle durch eine andere abgedeckt wird.

Ein freshness hold für brandneue Releases

Jedes Paket, das vor weniger als drei Tagen veröffentlicht wurde, wird standardmäßig zurückgehalten – das ist der Zeitraum, in dem eine kompromittierte Version normalerweise auf Packagist live ist, aber noch in keinem Sicherheitshinweis-Feed aufgeführt wird. Das ist bewusst als vorübergehende Funktion gedacht: Sobald Composer eine eigene Richtlinie zum Alter von releases einführt, wird dieser Teil abgeschafft. Brauchst Du eine bestimmte aktuelle Version, der Du vertraust? Mit --min-age 0 lässt Du sie durch.

„Bin ich schon infiziert?“ – Safe-Scan

Sobald ein Vorfall in den Nachrichten auftaucht, liest safe-scan Deine lockfile, überprüft jedes installierte Paket erneut und durchsucht vendor/ auf der Festplatte nach Anzeichen für einen Angriff – C2-Domains von Angreifern, URLs zur Datenexfiltration, Pfade zu eingeschleusten Dateien. Es führt niemals etwas aus und lädt auch nichts herunter; es beantwortet lediglich die Frage, die Du Dir um 2 Uhr morgens tatsächlich stellst: Ist dieses Projekt bereits mit etwas Schädlichem infiziert?

Installiere es und nutze es

Installieren

composer require sharkyger/composer-cve-gate --dev

Das Plugin registriert sich automatisch – die drei Befehle erscheinen sofort in composer list, ohne dass eine Konfigurationsdatei erstellt werden muss. Bei einem DDEV-Projekt (TYPO3, Drupal, Laravel, Symfony…) installiere stattdessen das Add-on, damit der Scan innerhalb des Web-Containers mit der PHP-Version durchgeführt wird, die Deine App tatsächlich verwendet:

ddev add-on get sharkyger/composer-cve-gate

Benutz es

composer safe-install monolog/monolog     # scan a new package + its tree, then install only if clean
composer safe-upgrade                      # scan every direct dependency, then update
composer safe-scan                         # audit what is already installed (+ on-disk infection check)

Damit composer install den Build bei einem Fehler (anstatt einer Warnung) abbricht, stelle das gate in Deinem Root composer.json auf den Blockiermodus um:

{ "extra": { "composer-cve-gate": { "install-gate": "block" } } }

Die vollständige Konfiguration, die Exit-Codes, der DDEV-Workflow und ein reproduzierbarer Docker-Proof sind auf GitHub zu finden: github.com/sharkyger/composer-cve-gate (MIT).

FAQ

Inwiefern unterscheidet sich „composer-cve-gate“ von „composer audit“?

composer audit wird nach der Installation ausgeführt und meldet Probleme erst, wenn der Code eines Pakets bereits auf der Festplatte liegt und möglicherweise bereits ausgeführt wurde. composer-cve-gate überprüft zum Zeitpunkt composer install anhand der lockfiles und blockiert ein markiertes Paket, bevor Composer es herunterlädt oder dessen Skripte nach der Installation ausführt.

Blockiert Composer nicht schon jetzt fehlerhafte Pakete?

Aktuelle Composer-Versionen blockieren standardmäßig bekannte Sicherheitswarnungen und Malware, wenn Du Pakete hinzufügst oder aktualisierst – eine echte Verbesserung, und Du solltest diese Funktion aktiviert lassen. Die Schwachstelle, die „composer-cve-gate“ schließt, betrifft die Neuinstallation: Wenn eine Schwachstelle veröffentlicht wird, nachdem Dein composer.lock committet wurde, lädt ein späteres composer install diese gesperrte Version ohne Blockierung neu. composer-cve-gate sperrt diesen Pfad ab und fügt zusätzlich eine freshness hold sowie einen Scan auf Infektionen auf der Festplatte hinzu.

Funktioniert das mit TYPO3, Drupal oder Laravel über DDEV?

Ja. Ein DDEV-Add-on führt den Scanner innerhalb des Web-Containers anhand der PHP-Version aus, die Deine App tatsächlich verwendet, und gibt ddev safe-install, safe-upgrade und safe-scan zurück – die PHP-Version auf Deinem Host spielt also keine Rolle.


composer-cve-gate ist eines der 5bats supply-chain gates – dasselbe Konzept wie bei der Vorinstallation von Python , Homebrew und die Pakete, die ein KI-Assistent installiert .

Siehe die Quelle, die Konfiguration und die DDEV-Anleitung auf GitHub →