
Host-unabhängiger Pre-Write-Sicherheits-Hook für Coding-Agenten: erkennt Benutzereingabemuster via Semgrep und gibt deterministische, LLM-freie Sicherheitsanweisungen aus.
Ein Sicherheits-Checkpoint für KI-Coding-Tools. Es prüft jede Datei, die ein KI-Assistent schreibt, und stoppt die gefährlichen, bevor sie die Festplatte erreichen.
KI-Coding-Assistenten (Claude Code, Codex, …) schreiben schnell Code – auch Code, der Dinge wie Passwörter, E-Mails, API-Schlüssel oder rohe Benutzereingaben verarbeitet. Es passiert leicht, dass ein Assistent diese Daten direkt in eine Datenbankabfrage, einen Shell-Befehl oder eine HTTP-Antwort einbaut, ohne an Sicherheit zu denken.
VibeGate sitzt zwischen dem Assistenten und Ihrem Dateisystem. Jedes Mal, wenn der Assistent versucht, eine Datei zu schreiben oder zu bearbeiten, scannt VibeGate den neuen Code zuerst:
An der Analyse selbst ist kein LLM beteiligt – es ist eine schnelle, deterministische statische Analyse, die nie etwas erfindet und nie Tokens kostet.
Hier ist alles, was VibeGate derzeit überprüft:
| Prüfung | Was sie erfasst | Ergebnis |
|---|---|---|
| Befehlseinschleusung | Unbereinigte Eingabe erreicht einen Shell-Befehl | Blockiert |
| SQL-Injection | Unbereinigte Eingabe erreicht eine Datenbankabfrage | Blockiert |
| NoSQL-Injection | Der Anforderungstext wird direkt als Datenbankfilter verwendet | Blockiert |
| Template-Injection (SSTI) | Die Template-Quelle selbst, nicht nur ihre Daten, stammt von Benutzereingaben | Blockiert |
| Unsichere Deserialisierung | Unvertraute Daten erreichen einen unsicheren Deserialisierer (pickle, unsicheres YAML, ...) | Blockiert |
| Path Traversal | Unbereinigte Eingabe erreicht einen Datei-Lese-, -Schreib- oder -Löschvorgang | Blockiert |
| XXE | Unvertrautes XML wird mit aktivierten externen Entitäten geparst | Blockiert |
| XSS | Unbereinigte Eingabe wird als rohes HTML ausgegeben | Blockiert |
| Uneingeschränkter Datei-Upload | Der eigene Name der hochgeladenen Datei wird zum Erstellen des Speicherpfads verwendet | Blockiert |
| SSRF | Der Server ruft eine URL ab, die nicht fest codiert ist | Warnt |
| Offene Weiterleitung | Ein Weiterleitungsziel, das nicht fest codiert ist | Warnt |
| Massenzuweisung | Der gesamte Anforderungstext wird an einen Modellkonstruktor oder eine Update-Funktion übergeben | Warnt |
| Sensible Daten im Anforderungstext | E-Mails, Passwörter, Token usw., die aus dem Anforderungstext gelesen werden | Warnt |
| Sensible Daten in einer URL/Abfrage | E-Mails, Passwörter, Token usw., die aus der Abfragezeichenfolge gelesen werden | Warnt |
| Sensible Daten in Headern | E-Mails, Passwörter, Token usw., die aus Anforderungs-Headern gelesen werden | Warnt |
| Dateipfad aus Benutzereingabe | Eine Variable, kein fest codierter String, wird als Dateipfad verwendet | Warnt |
| CLI-Argumente | Daten stammen aus Befehlszeilenargumenten | Warnt |
| Standard-Eingabe | Daten stammen von stdin | Warnt |
| Umgebungsvariablen | Daten stammen aus einer Umgebungsvariable | Warnt |
Die vollständige, aktuelle Liste befindet sich in guidance.TECHNICAL_RISKS und
formatter.BLOCKING_CATEGORIES, falls diese Tabelle jemals abweicht.
┌───────────────────────────────┐
│ You ask Claude Code to │
│ write or edit a file │
└───────────────┬───────────────┘
│
▼
┌───────────────────────────────┐
│ Claude Code tries to save │
│ the file (Write/Edit tool) │
└───────────────┬───────────────┘
│
▼
┌───────────────────────────────┐
│ VibeGate hook │
│ (runs automatically, │
│ before the file is saved) │
└───────────────┬───────────────┘
│
scans the new code with Semgrep
│
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
┌────────────────────┐ ┌────────────────────┐ ┌──────────────────────┐
│ No risky input │ │ Risky input, │ │ Risky input reaches │
│ found │ │ but lower risk │ │ a critical sink │
│ │ │ (e.g. shown in │ │ (SQL/command/RCE, │
│ │ │ an HTTP reply) │ │ template injection) │
└─────────┬──────────┘ └─────────┬──────────┘ └───────────┬──────────┘
│ │ │
▼ ▼ ▼
File is saved, File is saved, File is NOT saved.
nothing shown. plus a warning in Claude Code sees
the terminal with the block reason
risk + how to fix it. and is told what
to fix.
Kurz gesagt: Sicherer Code passiert unberührt, riskanter aber überlebensfähiger Code wird mit einer Warnung gespeichert, und Code, der nur einen Schritt von SQL-Injection, Befehlseinschleusung oder Remote-Code-Ausführung entfernt ist, wird gestoppt, bevor er die Festplatte erreicht.
Wenn VibeGate selbst auf einen unerwarteten Fehler stößt, lässt es den Schreibvorgang immer durch – ein Fehler im Hook sollte niemals der Grund dafür sein, dass Ihre Arbeit blockiert wird.
Jede Warnung und jeder Block enthält auch eine explizite Anweisung an Claude Code, den Fund in seiner Antwort zu erwähnen, nicht nur stillschweigend zu beheben. Dadurch wird die Aktivität von VibeGate im Gespräch sichtbar, nicht nur in einem Terminalprotokoll, das Sie erst suchen müssten.
| Was VibeGate sieht | Was passiert |
|---|---|
| Keine Benutzereingabe oder eine noch nicht unterstützte Sprache | Datei wird normal gespeichert, nichts wird angezeigt |
| Benutzereingabe gefunden, aber das Risiko ist moderat (z. B. offene Weiterleitung, Massenzuweisung) | Datei wird gespeichert, Terminal zeigt eine Warnung + Anleitung |
| Benutzereingabe fließt unbereinigt in eine kritische Senke (SQL/NoSQL-Abfrage, Shell-Befehl, Template-Engine, Deserialisierer, XML-Parser, Dateipfad, hochgeladener Dateiname oder rohe HTML-Ausgabe) | Datei wird nicht gespeichert – Claude Code wird der Grund mitgeteilt |
Die vollständige, pro Prüfung aufgeschlüsselte Liste dessen, was blockiert vs. nur warnt, finden Sie in der Tabelle unter "Welches Problem wird gelöst?" oben.
Derzeit versteht VibeGate Python, JavaScript/TypeScript, Go, Java, PHP und Ruby und bindet sich in Claude Code und Codex ein. Weitere Sprachen und Tools können hinzugefügt werden, ohne die Kernlogik zu berühren.
Es überprüft auch GitHub Actions-Workflow-Dateien auf zwei häufige CI/CD-
Lieferkettenfehler: Aktionen, die auf einen veränderlichen Tag (@v4) anstatt auf einen
Commit-SHA fixiert sind, und den unsicheren pull_request_target-Trigger. Beides
verursacht Warnungen, keine Blockaden, da es sich um Härtungsprüfungen handelt und nicht
um den Nachweis eines aktiven Exploits.
Hier ist eine echte Aufnahme von Claude Code, das eine RSS-Feed-Reader-App von Grund auf erstellt, während VibeGate die ganze Zeit läuft. Achten Sie auf die Momente, in denen Claude Code anhält und explizit sagt, was VibeGate markiert hat und warum, bevor es fortfährt – einschließlich eines echten SSRF-Risikos im Feed-Abruf-Code, das es sofort behebt.
Hier ist ein zweites Beispiel als Standbild: Claude Code erstellt eine App, mit der Benutzer ein Foto hochladen und seine Details anzeigen können. VibeGate bemerkt, dass der Dateiname und andere Dateidetails später auf dem Bildschirm angezeigt werden, und warnt, dass dies zur Einschleusung schädlichen Codes in die Seite verwendet werden könnte (dies wird XSS genannt). Claude Code passt den Code an, sodass Informationen sicher angezeigt werden.
In beiden Fällen wurde nichts grundlos blockiert, und niemand musste den Code Zeile für Zeile durchgehen, um das Problem zu finden. VibeGate hat es im Moment des Dateischreibens erwischt, und die KI hat es sofort behoben.
Es gibt zwei Möglichkeiten, einen KI-Assistenten dazu zu bringen, sichereren Code zu schreiben. Eine Möglichkeit besteht darin, vor dem Start einen großen Satz von Anweisungen zur sicheren Programmierung in das Gespräch zu laden, zum Beispiel eine Checkliste, die SQL-Injection, XSS, Passwort-Handling, Datei-Uploads und mehr abdeckt. Die andere Möglichkeit ist das, was VibeGate tut: den Code automatisch prüfen, genau dann, wenn eine Datei geschrieben wird, und nur dann etwas sagen, wenn tatsächlich etwas falsch ist.
Der erste Ansatz kostet Tokens für jede einzelne Nachricht, ob benötigt oder nicht. Eine typische Checkliste zur sicheren Programmierung, die mehrere Risikokategorien abdeckt, kann leicht einige tausend Tokens hinzufügen. Wenn ein KI-Assistent in einer Sitzung 50 Dateien schreibt und diese Checkliste jedes Mal neu geladen oder im Kontext behalten wird, zahlen Sie möglicherweise für weit über hunderttausend Tokens an Ratschlägen, die meistens nicht auf die gerade geschriebene Datei zutreffen. Eine Login-Seite und eine einfache Datei mit Farbkonstanten benötigen nicht die gleichen Warnungen, aber eine geladene Checkliste kann sie im Voraus nicht unterscheiden.
VibeGate dreht dies um. Es bleibt stumm und kostet nichts extra für jede Datei, die kein riskantes Muster enthält. Nur wenn es etwas findet, wie Benutzereingaben, die in eine Datenbankabfrage fließen, fügt es eine kurze, spezifische Notiz zu diesem einen Problem hinzu, meist ein kleiner Bruchteil der Größe einer vollständigen Checkliste. Anstatt also für jede Datei unabhängig vom Inhalt einen festen Token-Preis zu zahlen, zahlen Sie einen kleinen Preis nur für die Dateien, die tatsächlich Aufmerksamkeit benötigen, und dieser Preis zielt genau auf das gefundene Problem ab, nicht auf eine allgemeine Sicherheitsvorlesung.
Dies macht die Anleitung auch zuverlässiger. Ein KI-Assistent, der beim Schreiben von hundert Zeilen Code gebeten wird, "Sicherheit im Hinterkopf zu behalten", kann eine riskante Zeile unter vielen einfach übersehen. Ein Gate wird nicht müde oder abgelenkt: Es prüft jedes einzelne Schreiben, jedes Mal, unter Verwendung derselben festgelegten Regeln.
Einmal installieren – dies installiert auch Semgrep, auf das VibeGate angewiesen ist:
pipx install git+https://github.com/theMiddleBlue/vibegate
Dann aktivieren Sie es in dem Projekt, das Sie schützen möchten:
cd your-project
vibegate on # hier aktivieren (danach Claude Code neu laden)
vibegate status # prüfen, ob es für dieses Projekt aktiviert ist
vibegate off # hier deaktivieren
vibegate on fügt einen PreToolUse-Hook für Write|Edit|MultiEdit zur
.claude/settings.local.json dieses Projekts hinzu. Es ist projektbezogen, daher
beeinflusst das Aktivieren in einem Repository keine anderen.
Claude Code führt den Hook als vibegate run --host claude_code aus – keine
absoluten Pfade, daher funktioniert es auch nach einer Neuinstallation oder
Verschiebung.
vibegate status zeigt auch ein laufendes Protokoll dessen, was VibeGate in diesem
Projekt tatsächlich abgefangen hat – jede Warnung und jeden Block mit Datei, Zeile und
Kategorie –, sodass Sie seine Aktivität im Zeitverlauf sehen können, nicht nur, ob es
eingeschaltet ist:
$ vibegate status
█ █ █████ ████ █████ ████ ███ █████ █████
...
● VibeGate is ENABLED in .claude/settings.local.json
Recent activity (last 2 of 2 recorded, most recent first):
2026-07-02T17:35:48+00:00 ⛔ BLOCKED server.py:3 EXEC_INPUT (FREE_TEXT)
2026-07-02T17:35:46+00:00 ⚠ WARNED app.py:2 HTTP_BODY (EMAIL)
Dieses Protokoll befindet sich unter .vibegate/activity.jsonl im Projektstamm –
fügen Sie es Ihrer .gitignore hinzu, es ist lokaler Entwicklerstatus, kein
Einchecken.
VibeGate ermittelt, mit welchem Host es spricht, in dieser Reihenfolge: ein explizites
--host <name>-Flag, dann die Umgebungsvariable VIBEGATE_HOST, dann automatische
Erkennung aus der eingehenden Nutzlast, mit Fallback auf claude_code.
Wenn VibeGate etwas markiert, das Sie bewusst als sicher entschieden haben, fügen Sie
einen Kommentar vibegate-ignore in derselben Zeile hinzu – es funktioniert mit jeder
Kommentarsyntax (#, //, …), da VibeGate nur nach dem Text sucht:
query = f"SELECT * FROM users WHERE id = {user_id}" # vibegate-ignore
Um nur bestimmte Kategorien zu unterdrücken, anstatt alles in dieser Zeile, listen Sie sie nach einem Doppelpunkt auf (stimmt entweder mit der technischen Kategorie oder dem semantischen Typ überein, durch Kommas getrennt, Groß-/Kleinschreibung egal):
query = f"SELECT * FROM users WHERE id = {user_id}" # vibegate-ignore: DB_QUERY
src/vibegate/
├── hook.py # entry point
├── cli.py # on/off/status commands + the ASCII banner
├── activity_log.py # persists warnings/blocks to .vibegate/activity.jsonl
├── colors.py # shared ANSI color codes (report + CLI banner)
├── core.py # the host-agnostic pipeline
├── models.py # InputEvent / ClassifiedFinding / AnalysisResult
├── semgrep_runner.py # runs Semgrep as a subprocess (fail-safe)
├── classifier.py # maps Semgrep rule → category, variable name → data type
├── guidance.py # the static risk/remediation write-ups
├── formatter.py # turns results into a terminal report + host context
├── adapters/ # base, claude_code, codex + a small registry
└── rules/ # Semgrep rules — one file per language (Python, JS/TS,
# Go, Java, PHP, Ruby) plus a generic placeholder
Die Pipeline selbst (core.py) kommuniziert nie direkt mit einem bestimmten Host – die
gesamte host-spezifische Ein-/Ausgabe befindet sich in adapters/, sodass das Hinzufügen
eines neuen Hosts keine Änderungen an der Analyselogik erfordert.
semgrep --validate --config src/vibegate/rules/ # check the rules are valid
pytest tests/ # unit + integration tests
Um den gesamten Ablauf ohne Claude Code zu sehen:
python3 -c 'import json; print(json.dumps({"tool_name":"Write","tool_input":{"file_path":"/tmp/t.py","new_content":"email = request.json.get(\"email\")"}}))' \
| python3 src/vibegate/hook.py --host claude_code
rules/<lang>-user-input.yaml hinzufügen, die neuen
Regel-IDs in classifier.RULE_TO_TECHNICAL registrieren und die Dateierweiterung in
core.EXT_TO_LANGUAGE zuordnen.classifier.VARNAME_TO_SEMANTIC und eine Beschreibung in guidance.SEMANTIC_GUIDANCE
hinzufügen.RULE_TO_TECHNICAL
und eine Karte in guidance.TECHNICAL_RISKS hinzufügen.adapters/ hinzufügen und
in adapters/__init__.py registrieren.codex-Adapter ist eine frühe, bestmögliche Zuordnung. Überprüfen Sie seinen
Ereignisvertrag mit Ihrer Codex-Version, bevor Sie sich darauf verlassen, dass er etwas
blockiert."requires login" anstelle der tatsächlich
übereinstimmenden Zeile zurück, daher rekonstruiert der Klassifikator den Ausschnitt
selbst aus dem Dateiinhalt anhand der Zeilennummern.Edit/MultiEdit rekonstruiert der claude_code-Adapter die vollständige
Datei nach der Bearbeitung von der Festplatte, sodass eine verunreinigte Quelle und eine
Senke, die durch getrennte Bearbeitungen eingeführt wurden, dennoch verbunden sind –
aber es werden nur Funde auf den Zeilen gemeldet, die die Bearbeitung tatsächlich
berührt hat. Wenn eine Senke bereits existiert und eine spätere Bearbeitung nur die
verunreinigte Quelle hinzufügt, die sie erreicht, wird dies nicht erfasst (die Zeile
der Senke war nicht Teil der neuen Bearbeitung). Diese Rekonstruktion ist Claude-Code-
spezifisch; der codex-Adapter macht dies noch nicht.| Nicht fixierte GitHub-Aktion |
Ein Workflow verwendet einen veränderlichen Tag (@v4) anstelle eines Commit-SHA |
| Warnt |
Unsicheres pull_request_target | Ein Workflow verwendet den pull_request_target-Trigger | Warnt |
| Protokollierung von Anmeldeinformationen | Ein Passwort, API-Schlüssel oder Token wird an print/console.log/einen Logger übergeben | Warnt |
| Hartcodiertes Geheimnis | Eine Variable, die wie ein Geheimnis benannt ist, erhält einen echt aussehenden Literalwert | Warnt |