Der Scan meldete sicher — und das bloße Ansehen des Skills hat ihn ausgeführt


Ein Community-Skill wird aus einem Hub installiert. Eine Zeile installed blitzt vorbei, der Scan-Report meldet sicher, und weiter geht es. Drei Wochen später wird der Skill in einer Session nur zum Anschauen geöffnet — und etwas läuft.

Der gefährliche Moment war nicht die Installation. Es war das Anschauen. Hier steht, was der Skills-Guard tatsächlich scannt, welche drei Fälle er übersehen hat und welche eine Aufräumaktion sich heute lohnt.

Wie der Guard arbeitet

Extern bezogene Skills durchlaufen einen statischen Regex-Scan, danach entscheidet eine trust-bewusste Install-Policy, ob sie landen:

Trust-Stufe Urteil safe Urteil caution Urteil dangerous
builtin (mitgelieferte Skills) allow allow allow (wird nie gescannt)
trusted (openai/skills, anthropics/skills, huggingface/skills, NVIDIA/skills) allow allow block
community (jede andere Quelle) allow block block
agent-created allow allow Fehler zurück an den Agent (nur wenn skills.guard_agent_created aktiv ist)

Jedes Urteil wird zusammen mit einer Scanner-Version gecacht (SCANNER_VERSION, vor diesem Fix v6). Diese Version zählt: Ändert sie sich, zählen gecachte Urteile nicht mehr, und der Skill wird neu gescannt.

Die drei blinden Flecken

1. Nur ein wörtliches $HOME zählte als Home

Die Regel, die „lösche das Home-Verzeichnis“ abfängt, matchte den wörtlichen String $HOME:

rm -rf $HOME/Documents     → gematcht, kritisch
rm -rf ~/Documents         → übersehen, als sicher eingestuft

Also kam rm -rf ~/Documents auf jeder Trust-Stufe durch. Der Fix matcht auch nackte Tilde-Formen (~/, ~ , ~*, ~$), für rm und rmdir.

2. Niemand beobachtete die !cmd`` Auto-Exec-Syntax

Hermes-Skills unterstützen ein Inline-Shell-Fragment: Ein !`cmd` im Skill-Body wird über bash -c expandiert, wenn der Skill angesehen oder geladen wird. Es ist standardmäßig aus und wird explizit konfiguriert:

skills:
  inline_shell: false        # standardmäßig aus; nur für Quellen aktivieren, denen man vertraut
  inline_shell_timeout: 10   # Sekunden pro !`cmd`-Snippet

Doch keine Scan-Regel entsprach dem. Ein Skill, dessen Body !`rm -rf ~/Documents` enthielt, wurde als sicher gescannt, installiert und dann beim nächsten Öffnen ausgeführt.

Der Fix ergänzt ein inline_shell_exec-Muster (Severity high, Kategorie execution). Es verlangt eine Nicht-Leerzeichen-Payload, damit ein Skill, der die Syntax nur dokumentiert, nicht markiert wird.

3. Eine blockierte Installation meldete sich als erfolgreich

Der dritte Fall ist überhaupt keine Scan-Regel — es ist die Schnittstelle. Der TUI-Gateway-Install-Pfad führte do_install(skip_confirm=True) mit einer Sink-Konsole aus und gab bedingungslos installed: True zurück.

Blockierte der Security-Scan also einen Skill, erfuhr der Aufrufer (etwa eine Ein-Klick-Installation in der Desktop-App), die Installation sei gelungen. Nach dem Fix kommt installed: True nur noch von einer echten Installation zurück; Fehlschläge liefern einen Fehler-Envelope (Code 5031), dessen Nachricht und data.log den ausgegebenen Tail tragen — die Erklärung der Scan-Blockierung, die Kandidatentabelle der Mehrdeutigkeit oder den Fetch-Fehler —, statt ihn in einen Sink zu kippen.

Werden bereits vorhandene Skills erneut gescannt?

Ja — und das läuft über den Versionsstempel, nicht über eine Neuinstallation. Da Cache-Einträge scanner_version speichern, gilt, sobald der Scanner auf v7 wandert:

  • zuvor gecachte „safe“-Urteile werden ungültig;
  • installierte Hub-Skills werden unter v7 neu gescannt, wenn sie geprüft werden;
  • alles neu Installierte läuft direkt durch v7.

Der zweite Punkt ist der entscheidende: Läuft auf der Maschine noch der v6-Scanner, war die Schlussfolgerung „ich habe es gescannt, es war sicher“ für den Nackte-Tilde-Fall nie gültig — die Regel existierte einfach nicht.

Was jetzt zu tun ist

  1. Die Scanner-Version bestätigen. Nach dem Update auf einen Build mit dem Fix sollte SCANNER_VERSION in tools/skills_guard.py skills-guard-v7 lauten (vorher war es v6).
  2. Bereits Installiertes neu scannen. Das ist der wichtige Punkt:
    hermes skills audit
    Es scannt installierte Hub-Skills erneut. Die vollständige Liste der Subcommands steht in der hermes skills-Referenz, und wo Skills zu finden sind, behandelt Skill-Hubs und Suchquellen.
  3. skills.inline_shell aus lassen, außer die Quelle ist vertrauenswürdig. Das Flag ist als explizites Opt-in für vertrauenswürdige Quellen dokumentiert; dieser Fix hat es bewusst nicht auf bestimmte Trust-Stufen beschränkt (das ist eine Produktentscheidung), die Regel macht das Risiko also nur zur Installationszeit sichtbar.
  4. Die Grenzen des Scanners kennen. Er ist Regex, keine Datenflussanalyse. Die eigenen Modulnotizen nennen eine bekannte Lücke: Schreib-APIs der Sprache — open(..., 'w'), Path.write_text, shutil.copy* —, die auf Agent-Config-Dateien zielen, erzeugen nur einen Referenz-Befund mit niedriger Severity, weil ein statischer Regex den Aufruf nicht an ein dynamisch berechnetes Ziel binden kann. Den Scan zu bestehen ist nicht dasselbe, wie ihn blind laufen zu lassen.
  5. Auch von Agents erstellte Skills prüfen. Ist skills.guard_agent_created aktiv, wird ein gefährliches Urteil über einen vom Agent geschriebenen Skill als Fehler an den Agent zurückgegeben, damit er ihn umschreiben kann; das fängt offensichtliche schlechte Muster ab, ist aber kein Review.

Um die Grenze weiter zu schärfen, behandelt projektlokale Skills und das Trust-Gate, wie im Repo mitgelieferte Skills in die Trust-Entscheidung eingehen, während optionale Skills und den MCP-Katalog sicher nutzen zwei andere Seiten derselben Frage sind.

Aktueller Stand

PR #128443 wurde am 2026-09-30 in main gemergt; es gibt einen früheren Report aus derselben Problemfamilie (Issue #63307, das verschluckte Scan-Urteil beim Install-RPC). Der neueste Tag v0.21.5 ist vom 24.09., Tags liefern also noch den v6-Scanner — Git-Installationen, die main tracken, sind bereits auf v7.

Das Fazit

Die drei blinden Flecken haben eine gemeinsame Form: Der Scanner schaut auf die geschriebenen Zeichen, während das eigentliche Risiko oft darin liegt, wie diese Zeichen ausgeführt werden. $HOME und ~ sind dasselbe Verzeichnis; !`...` und bash -c ... sind dieselbe Ausführung. Das statische Matching sieht das Erste und übersieht das Zweite.

Die wertvollste einzelne Aktion ist kurz: nach dem Update hermes skills audit ausführen. Es prüft die bereits auf der Maschine liegenden Skills unter v7 erneut — und einige davon wurden nie wirklich geprüft.