Hermes fragt jetzt nach, bevor Pakete deinstalliert werden

Ein globales npm-Paket bremst deine Builds aus, ohne dass du weißt warum. Du findest es, tippst npm uninstall -g some-package und drückst Enter, ohne weiter darüber nachzudenken. Zwei Tage später fehlt es in der CI, und alle Projekte auf dieser Maschine sind mit betroffen. Etwas zu installieren fällt auf. Etwas zu löschen vergisst man leicht – und der Schaden trifft meist mehrere auf einmal. Und trotzdem hielt damals nichts an, als Hermes Agent dieses Kommando für dich ausführte: Das Genehmigungs-Gate für gefährliche Kommandos kannte nur Shell-Primitive wie rm -rf. PR #109170 schließt genau diese Lücke.
Installation tut selten weh, Löschen schon
Zuerst der Mechanismus. Die Genehmigung gefährlicher Kommandos ist ein Satz eingebauter Musterregeln in Hermes: Wenn der Agent ein Kommando ausführen will, dessen Folgen sich nicht rückgängig machen lassen, zeigt er eine Genehmigungsabfrage und wartet auf dich, statt einfach loszulegen. Der Gedanke dahinter ist schlicht: Ein unwiderruflicher Vorgang soll nicht unbemerkt durchrutschen.
Unter diesem Blickwinkel sind Installieren und Deinstallieren nicht symmetrisch. Installieren ist additiv: Was dazukommt, fällt dir früh genug auf, und wenn es Ärger macht, löschst du es wieder. Deinstallieren ist subtraktiv, und meistens geteilte Subtraktion: Ein global entferntes Paket betrifft jedes Projekt auf der Maschine, das davon abhing – und nichts sagt dir, dass gerade etwas verschwunden ist.
Genau diese Asymmetrie ist der Grund, warum die Änderung nur das Löschen abfängt. npm update -g, pip install, brew upgrade und yarn install werden weiterhin nicht markiert und fragen weiterhin nicht nach. Würde man auch die Installationsseite gaten, wäre die Abfrageleiste nur noch Rauschen, das man dutzendfach am Tag wegklickt – schlechter als gar kein Gate.
Die Musterliste kannte nur Shell-Primitive
Das Problem steckte in DANGEROUS_PATTERNS, der Musterliste in tools/approval_detection.py. Was sie erkannte, waren Shell-Primitive: rm -rf, git reset --hard und Verwandte – grob, allgemein bekannt, auf den ersten Blick offensichtlich. Für Löschverben von Paketmanagern gab es keine einzige Regel.
Als der Vorfall aus Issue #10199 tatsächlich passierte, lief das Kommando deshalb ohne jede Rückfrage bis zum Ende durch. Kein falsches Urteil, sondern: keine Regel deckte dieses Kommando ab.
Diese fünf Lösch-Schreibweisen werden jetzt gestoppt
PR #109170 geht den direkten Weg und ergänzt in DANGEROUS_PATTERNS pro Paketmanager eine Regel "package manager uninstall". Der gesamte Diff ist +34 / −0 über zwei Dateien, tools/approval_detection.py und tests/tools/test_approval.py.
Ab jetzt laufen diese Kommandos durch die Genehmigung für gefährliche Kommandos:
- npm –
npm uninstall -g some-package. Löschverben:uninstall/unlink/remove/rm/r/un - pnpm –
pnpm remove. Löschverben:uninstall/remove/rm/un - yarn –
yarn remove. Die Regel erlaubt davor ein optionalesglobal, danachuninstall/remove - pip / pip3 –
pip uninstall. Das Löschverb istuninstall - brew –
brew uninstall. Löschverben:uninstall/remove/rm
Wichtig ist, worauf die Regeln matchen: auf das Löschverb des Managers, nicht auf einen bestimmten Paketnamen. Worauf das Verb auch zielt und wie viele Ziele folgen – das Kommando wird markiert.
An zwei Stellen haben sie Fehlalarme vermieden
Der klassische Weg, eine Musterliste kaputtzumachen, ist eine zu breite Regel, die anfängt, legitime Kommandos zu blockieren. Zwei Details sind hier erwähnenswert.
Erstens: Die Regeln sind mit _CMDPOS an die Kommandoposition verankert. Wie die übrigen Kommandonamen-Regeln in dieser Datei greift das Muster nur dort, wo das Kommando tatsächlich beginnt. Text in „Anführungszeichen“ wird deshalb nicht falsch gedeutet – git commit -m "document npm uninstall usage" ist nur eine Commit-Nachricht und löst nichts aus.
Zweitens: Jede globale Option darf ein Argument haben, das kein Bindestrich ist. Also werden auch npm --prefix DIR uninstall x, pip --proxy URL uninstall x und yarn --cwd DIR remove x erfasst. Eine Option mit einem Argument dahinter ist eine alltägliche Form; verpasst man sie, ist die Regel bloß Dekoration.
Die Tests kamen mit. tests/tools/test_approval.py ergänzt 6 parametrisierte Fälle, die sechs Lösch-Schreibweisen auf einen einzigen Key zusammenfassen. Gegen den alten Code waren diese Fälle rot; nach der Korrektur laufen 129 Fälle durch, und die komplette Suite in tests/tools/ steht mit 9141 grün.
Was das für dich bedeutet
Wenn jemand deine Hermes-Sitzung im Blick hat, ist die Sache einfach: Der Agent hält an und fragt, bevor er ein Paket deinstalliert, und du bestätigst oder lehnst ab. Ein zusätzlicher Klick dafür, dass am Ende „das Gelöschte auch das Gewollte“ ist.
Der Fall, über den man wirklich vorher nachdenken sollte, ist unbeaufsichtigte Arbeit – Cron-Jobs, Agenten im Hintergrund. Dort ist niemand, der eine Abfrage beantwortet, also bleibt eine Deinstallation, die eigentlich hätte gestoppt werden sollen, auf halbem Weg stehen. Wenn ein automatisierter Ablauf wirklich Pakete deinstallieren muss, verlass dich nicht darauf, dass es einfach durchläuft: Probelauf mit hermes approvals test gegen die echten Wächter, schau, welches Urteil dabei herauskommt, und entscheide dann, ob du es erlaubst, den Ablauf umbaust oder den Agenten ganz von diesem Schritt fernhältst. Wie sich Genehmigungen im Cron-Kontext verhalten, steht ausführlicher im Leitfaden für unbeaufsichtigte Genehmigungen.
Eine Unterscheidung, die man sauberhalten sollte: Die Genehmigung gefährlicher Kommandos und approvals.deny sind zwei verschiedene Mechanismen. Ersteres ist die eingebaute Musterliste und funktioniert ohne jede Konfiguration von dir; Letzteres ist eine vordefinierte Sperrliste, die du selbst pflegst. Dieser Artikel behandelt nur Ersteres. Für Letzteres siehe Smart Approvals einrichten – das muss hier nicht wiederholt werden.
Und zum Schluss der Veröffentlichungsstand, ohne Umschweife: Das ist am 2026-09-12 in main gelandet, also später als v0.21.2 (veröffentlicht am 2026-09-11). Es ist damit noch in keiner Version veröffentlicht – es steckt im Hauptzweig und erreicht dich mit der nächsten Version. Um zu sehen, was dein aktueller Stand tun würde, ist hermes approvals test die direkte Antwort; die Release Notes zu v0.21.2 sind die letzte Veröffentlichung vor dieser Änderung.
Kurz zusammengefasst
- Deinstallationen von Paketmanagern laufen jetzt durch die Genehmigung für gefährliche Kommandos:
npm uninstall -g,pnpm remove,yarn remove,pip uninstallundbrew uninstallsind abgedeckt. - Installationen und Updates fragen weiterhin nicht nach:
npm update -g,pip install,brew upgradeundyarn installsind nicht betroffen. Die Genehmigung bleibt dem wirklich Unwiderruflichen vorbehalten. - Die Regeln sind an die Kommandoposition verankert, deshalb wird ein
npm uninstallin Anführungszeichen nicht fälschlich markiert, und eine globale Option mit einem Argument hebelt sie nicht aus. - Die Änderung ist in
maingemergt und noch in keiner Version erschienen.