Ein einzelner API-Schlüssel im falschen Commit reicht aus, damit ein fremdes Konto oder eine ganze Datenbank offen liegt, sobald das Repository öffentlich wird oder ein einzelner Mitarbeiterzugang kompromittiert ist. Je mehr eigenständige Repositories eine Organisation gleichzeitig pflegt, desto weniger lässt sich das allein über Disziplin verhindern. Ein automatisierter Secret-Scan, der lokal vor jedem Commit und zusätzlich in der Pipeline läuft, fängt genau die Fälle ab, die ein Review übersieht, weil ein Schlüssel in einer Log-Zeile oder einer Testkonfiguration leicht untergeht.
Wie verbreitet das Problem ist, zeigt eine Zahl von GitGuardian: Allein auf öffentlichem GitHub kamen 2025 rund 28,65 Millionen neu fest codierte Zugangsdaten hinzu, ein Anstieg von 34 Prozent gegenüber dem Vorjahr und laut GitGuardian der größte je gemessene Sprung innerhalb eines Jahres. Bei Commits, die mit einem KI-Codierassistenten wie Claude Code entstanden, lag die Leak-Rate 2025 bei 3,2 Prozent und damit über dem Durchschnitt von 1,5 Prozent über alle öffentlichen Commits hinweg. Ein Scan vor dem Commit setzt genau an dieser Stelle an, bevor eine dieser Zahlen um einen weiteren Fund wächst.
Systemvoraussetzungen
Ein Secret-Scan-Workflow braucht wenige Bausteine, aber jeder davon muss zur aktuellen Version passen. Die folgende Tabelle nennt die Werkzeuge und wofür sie im Ablauf stehen.
| Komponente | Version oder Anforderung | Zweck |
|---|---|---|
| Gitleaks (CLI) | v8.30.1, veröffentlicht am 21. März 2026 | Musterabgleich und Entropieprüfung, lokal und in der Pipeline |
| TruffleHog (CLI) | v3.97.1, veröffentlicht am 24. August 2026 | Alternative mit Live-Verifizierung gefundener Zugangsdaten gegen die jeweilige API |
| pre-commit-Framework | Python ab Version 3.9, Installation per pip install pre-commit | Verwaltet den Git-Hook einheitlich über alle Repositories |
| GitHub Actions | gitleaks/gitleaks-action@v3, actions/checkout@v4 oder neuer | Pflichtprüfung bei Pull Requests, Pushes und geplanten Läufen |
| Gitleaks-Lizenz | GITLEAKS_LICENSE als Repository- oder Organisations-Secret | Nur für Organisations-Repositories nötig, kostenlos unter gitleaks.io erhältlich |
| git-filter-repo | Python ab Version 3.6 und Git ab Version 2.24.0 | Bereinigt ein bereits gepushtes Secret aus der gesamten Commit-Historie |
Systemarchitektur
Ein Secret ist in diesem Zusammenhang jede Zugangsinformation, die Zugriff auf ein System gewährt: ein API-Schlüssel, ein Datenbankpasswort, ein OAuth-Token oder ein privater Schlüssel. Ein Secret-Scan durchsucht Code und Commit-Historie nach Mustern, die zu bekannten Formaten solcher Zugangsdaten passen, und meldet Treffer, bevor sie irgendwo sichtbar werden. Der Ablauf hat zwei Kontrollpunkte, die sich ergänzen, aber einander nicht ersetzen. Der Pre-Commit-Hook prüft auf dem Rechner der Entwicklerin, bevor ein Commit überhaupt entsteht. Die Prüfung in GitHub Actions läuft danach noch einmal serverseitig, weil sich der lokale Hook mit einem einzigen Flag umgehen lässt.
flowchart TD
A[Entwicklerin aendert Code lokal] --> B[git commit wird ausgefuehrt]
B --> C[Pre-Commit-Hook startet Gitleaks]
C -->|Fund| D[Commit wird abgelehnt]
C -->|Kein Fund| E[Commit entsteht]
D --> A
E --> F[git push zum Remote-Repository]
F --> G[GitHub Actions Workflow startet]
G --> H[Gitleaks Action prueft den Pull-Request-Diff]
H -->|Fund| I[Pflichtpruefung schlaegt fehl, Merge blockiert]
H -->|Kein Fund| J[Pruefung besteht, Merge moeglich]
I --> K[Zugangsdaten sofort rotieren]
K --> L[Historie mit git filter-repo oder BFG bereinigen]
Der Scan läuft in drei Phasen. Lokal fängt Gitleaks den größten Teil der Fälle ab, weil ein abgelehnter Commit gar nicht erst in der Historie landet. In der Pipeline prüft dieselbe Regel-Engine noch einmal, diesmal ohne dass jemand sie versehentlich übergehen kann. Findet die Pipeline trotzdem ein Secret, endet der Ablauf nicht mit einer roten Prüfung, sondern mit der Rotation der betroffenen Zugangsdaten. Ein Scan schützt nicht rückwirkend. Nur ein neuer, ungültig gemachter Schlüssel entwertet das, was bereits im Netz sichtbar war, sobald der Push passiert ist.
Schritt-für-Schritt-Umsetzung
Pre-Commit-Hook lokal einrichten
Ein Pre-Commit-Hook ist ein Skript, das Git automatisch vor jedem lokalen Commit ausführt und den Commit stoppen kann, bevor er in der Historie landet. Die einfachste Art, einen solchen Hook für viele Repositories einheitlich aufzusetzen, ist das pre-commit-Framework: Es liest eine Konfigurationsdatei aus dem jeweiligen Repository und ruft die darin definierten Werkzeuge auf, Gitleaks eingeschlossen.
- pre-commit installieren. Am einfachsten per
pip install pre-commit, alternativ über Homebrew oder die Paketverwaltung des Betriebssystems. - Konfigurationsdatei anlegen. Im Wurzelverzeichnis des Repositories eine Datei namens
.pre-commit-config.yamlmit dem Verweis auf Gitleaks erstellen. - Hook installieren. Der Befehl
pre-commit installträgt den Hook in.git/hooks/pre-commitein. - Version aktuell halten.
pre-commit autoupdatezieht regelmäßig die neueste Gitleaks-Version in die Konfiguration.
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1
hooks:
- id: gitleaks
Wer den nativen Weg ohne das Framework bevorzugt, kopiert stattdessen das mitgelieferte pre-commit.py-Skript aus dem Gitleaks-Repository direkt nach .git/hooks/pre-commit. Dieser Weg spart die Python-Abhängigkeit des Frameworks, muss aber in jedem Repository einzeln gepflegt werden, während das Framework die Version zentral in einer Datei trägt. Ein Hook lässt sich jederzeit umgehen, etwa mit git commit --no-verify oder, beim pre-commit-Framework, mit SKIP=gitleaks git commit. Genau deshalb ist der Hook eine Vorstufe und keine alleinige Absicherung.
GitHub-Actions-Workflow für Pull Requests
Die eigentliche Kontrollstelle ist die Prüfung im Backend, weil sie sich nicht lokal abschalten lässt. Gitleaks stellt dafür eine offizielle GitHub Action bereit, aktuell in Version 3 (gitleaks/gitleaks-action@v3). Für Repositories, die einer Organisation gehören, verlangt die Action einen kostenlosen Lizenzschlüssel über die Umgebungsvariable GITLEAKS_LICENSE; bei einem persönlichen Konto entfällt das.
Ein vollständiger Scan der gesamten Historie bei jedem Push wird mit wachsender Repository-Größe langsam. Für einen Pull Request genügt es, nur die neuen Commits zu prüfen. Gitleaks bietet dafür die Option --log-opts, mit der sich der Bereich für git log frei eingrenzen lässt, zum Beispiel auf genau die Commits zwischen dem Basis- und dem Kopf-Stand eines Pull Requests.
name: secret-scan
on:
pull_request:
push:
branches: [main]
schedule:
- cron: "0 4 * * 1"
jobs:
gitleaks-pr:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Nur den Pull-Request-Diff scannen
run: |
docker run --rm -v "$(pwd):/repo" zricethezav/gitleaks:v8.30.1 \
git -v --log-opts="${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}" /repo
gitleaks-full:
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
Der erste Job scannt bei einem Pull Request ausschließlich die Commits zwischen Basis- und Kopf-Stand und bleibt dadurch auch in einem Repository mit jahrelanger Historie schnell. Der zweite Job läuft bei einem Push auf den Hauptzweig und zusätzlich einmal wöchentlich nach Zeitplan vollständig, damit ein Fund nicht allein von der Existenz eines Pull Requests abhängt.
Wiederverwendbare Workflow-Datei für viele Repositories
Wer denselben Workflow in vierzig Repositories per Copy-Paste pflegt, ändert bei jedem neuen Gitleaks-Release vierzig Dateien. GitHub Actions löst das mit wiederverwendbaren Workflows: Eine Workflow-Datei bekommt den Auslöser workflow_call und lässt sich danach aus jedem anderen Repository derselben Organisation aufrufen, solange die Berechtigungen es erlauben.
# liegt zentral, z. B. im Repository "org/.github"
# Pfad: .github/workflows/secret-scan-reusable.yml
on:
workflow_call:
secrets:
gitleaks-license:
required: false
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.gitleaks-license }}
# liegt in jedem einzelnen Projekt-Repository
# Pfad: .github/workflows/secret-scan.yml
name: secret-scan
on:
pull_request:
push:
branches: [main]
jobs:
call-secret-scan:
uses: org/.github/.github/workflows/secret-scan-reusable.yml@v1
secrets: inherit
Der Umweg über eine zentrale Datei kostet etwas. Eine fehlerhafte Änderung im geteilten Workflow wirkt sich sofort auf jedes aufrufende Repository aus, und Berechtigungen lassen sich beim Aufruf nur einschränken, nie erweitern, was eine Konfiguration gelegentlich verkompliziert. Kopierte YAML-Dateien haben den umgekehrten Nachteil: Jede Kopie kann unbemerkt vom Original abweichen, und eine neue Gitleaks-Version bedeutet eine Änderung je Repository statt einer einzigen. Für eine Handvoll Repositories reicht Kopieren aus. Bei mehreren Dutzend eigenständig gepflegten Repositories gleicht die eine zentrale Datei die zusätzliche Abhängigkeit meistens aus. Wichtig dabei: Die aufrufende Datei referenziert den geteilten Workflow über einen festen Tag wie @v1, nicht über einen sich ständig bewegenden Branch wie main, sonst übernimmt jedes Repository beim nächsten Lauf ungeprüft jede Änderung am Original.
Häufige Fehlerquellen
- Flache Historie in der Pipeline. Ohne
fetch-depth: 0beim Checkout sieht die Pipeline nur den letzten Commit, und ein Fund in einem älteren, aber neuen Commit des Pull Requests bleibt unentdeckt. Der Checkout-Schritt brauchtfetch-depth: 0, sobald Gitleaks über mehrere Commits hinweg prüfen soll. - Fehlende Lizenz in Organisations-Repositories. Läuft
gitleaks-actionohneGITLEAKS_LICENSEin einem Repository, das einer Organisation gehört, bricht die Prüfung sofort mit einem Lizenzfehler ab. Der Schlüssel ist kostenlos unter gitleaks.io erhältlich und gehört als Secret auf Organisationsebene hinterlegt, damit jedes Repository ihn erbt. - Falsch positive Funde durch die Entropieprüfung. Lange Base64-Blöcke, Testfixtures oder generierte IDs erreichen dieselbe Zufälligkeit wie ein echtes Secret und werden gemeldet, obwohl nichts geheim ist. In der Datei
.gitleaks.tomlreduziert ein eng gefasster Eintrag unter[[rules.allowlists]]genau diese Fälle, etwa über einen Dateipfad oder ein Stichwort, ohne die Regel insgesamt abzuschalten. Bei einer bereits bestehenden, langen Historie hilft zusätzlich ein Baseline-Report über--baseline-path, der alte Funde dauerhaft ausblendet und nur neue meldet. - Hook wird lokal umgangen.
git commit --no-verifyoderSKIP=gitleaks git commitlassen jeden Commit durch, auch einen mit Secret. Die Pflichtprüfung in GitHub Actions fängt genau diesen Fall auf, sofern sie als erforderlicher Status-Check für den Hauptzweig konfiguriert ist. - Gelöschte Zeile statt entferntem Secret. Ein Secret aus dem aktuellen Stand zu löschen und neu zu committen, entfernt es nicht aus der Historie. Jeder frühere Commit enthält die Zeile weiterhin und bleibt über
git log -poder einen Klon abrufbar. Nur das Rotieren der Zugangsdaten macht den alten Wert wertlos, unabhängig davon, ob die Historie später bereinigt wird. - Wiederverwendbarer Workflow zeigt auf einen beweglichen Verweis. Ruft die Aufrufdatei den geteilten Workflow über
@mainstatt über einen festen Tag auf, wirkt sich jede Änderung am geteilten Workflow sofort und ungeprüft auf alle aufrufenden Repositories aus. Ein fester Versions-Tag oder ein Commit-SHA imuses-Verweis verhindert das.
Häufig gestellte Fragen
Wird Gitleaks noch aktiv weiterentwickelt?
Gitleaks wird nach Angaben des eigenen Repositories nur noch mit Sicherheitskorrekturen gepflegt: Das Projekt gilt laut eigener Beschreibung als funktional abgeschlossen, und der ursprüngliche Autor Zach Rice konzentriert sich inzwischen auf ein neues Projekt namens Betterleaks. Für die reine Muster- und Entropieprüfung vor einem Commit oder in einer Pipeline ändert das wenig, weil die Erkennungslogik bereits stabil ist und keine neuen Funktionen braucht, um zuverlässig zu bleiben. Wer zusätzlich prüfen will, ob ein gefundenes Secret überhaupt noch gültig ist, findet das eher bei TruffleHog: Das Projekt von Truffle Security erschien mit Version 3.97.1 erst am 24. August 2026 und wird damit deutlich häufiger aktualisiert; es kann Zugangsdaten testweise gegen die jeweilige API prüfen, bevor ein Team Zeit in eine Rotation investiert.
Reicht ein Pre-Commit-Hook allein aus, um Secrets zuverlässig abzufangen?
Ein Pre-Commit-Hook allein reicht nicht aus, weil er sich mit einem einzigen Flag umgehen lässt. Sowohl der native Git-Hook als auch das pre-commit-Framework laufen ausschließlich auf dem Rechner der Entwicklerin, und Befehle wie git commit --no-verify oder SKIP=gitleaks setzen die Prüfung für genau diesen Commit außer Kraft. Die Pflichtprüfung in GitHub Actions ist deshalb der eigentliche Kontrollpunkt: Sie läuft serverseitig, lässt sich als erforderlicher Status-Check erzwingen und kann von niemandem lokal abgeschaltet werden. Der Hook bleibt trotzdem sinnvoll, weil er einen Fund vor dem Push meldet und damit einen Umweg über die Pipeline erspart.
Was ist zu tun, wenn ein Secret bereits in die Git-Historie gepusht wurde?
Ein bereits gepushtes Secret verlangt zuerst die Rotation der betroffenen Zugangsdaten, unabhängig davon, ob die Historie später bereinigt wird. GitHub beschreibt in seiner eigenen Dokumentation zum Entfernen sensibler Daten die Rotation als den entscheidenden Schritt: Ist ein Schlüssel widerrufen, kann er nicht mehr benutzt werden, und die anschließende Bereinigung der Historie senkt vor allem das Risiko, dass jemand die alte Kopie später wiederfindet. Für diese Bereinigung empfiehlt GitHub das Werkzeug git filter-repo, das einen Suchbegriff oder eine Datei aus jedem betroffenen Commit entfernt; BFG Repo-Cleaner leistet Ähnliches mit weniger Optionen, dafür oft schneller bei sehr großen Repositories. Keines der beiden Werkzeuge macht ein bereits offengelegtes Secret nachträglich sicher. Das leistet ausschließlich die Rotation.
Lohnt sich eine zentrale, wiederverwendbare Workflow-Datei für viele Repositories?
Eine zentrale Workflow-Datei lohnt sich, sobald mehr als eine Handvoll Repositories denselben Secret-Scan brauchen, weil eine Aktualisierung dann an einer Stelle passiert statt in jedem einzelnen Repository. Der zuständige Mechanismus heißt in GitHub Actions workflow_call: Eine Datei mit diesem Auslöser lässt sich aus jedem anderen Repository derselben Organisation per fester Versionsangabe aufrufen. Der Preis dafür ist eine zusätzliche Abhängigkeit, denn ein Fehler in der geteilten Datei wirkt sich auf alle aufrufenden Repositories gleichzeitig aus. Bei zwei oder drei Repositories bleibt eine einzeln kopierte YAML-Datei je Repository oft die einfachere Wahl.