Wie Geheimnisse durch Logs, Build-Artefakte und Git-History durchsickern

Sie haben gerade Ihre CI/CD-Pipeline eingerichtet, um Secrets sicher aus einem Vault zu beziehen. Die Pipeline läuft, die Anwendung wird deployed, alles sieht grün aus. Eine Woche später findet jemand im Team ein Datenbank-Passwort, das vor drei Tagen in einem Pipeline-Log ausgedruckt wurde. Niemand weiß, wer es gesehen hat. Niemand weiß, ob es kopiert wurde. Das Passwort ist jetzt praktisch öffentlich.

Dieses Szenario passiert häufiger, als Teams erwarten. Der Vault selbst ist sicher. Die Pipeline-Integration funktioniert. Aber Secrets sickern nicht immer durch das Speichersystem durch. Sie sickern durch die Stellen, an denen sie versehentlich landen: Logs, Build-Artefakte und Git-History.

Warum Pipeline-Logs eine Leckstelle sind

Pipeline-Logs sind der erste Ort, an dem Secrets entweichen. Während der Entwicklung oder Fehlersuche geben Teams oft Umgebungsvariablen aus, um zu sehen, was passiert. Wenn eine Anwendung keine Verbindung zur Datenbank herstellen kann, fügt jemand eine schnelle Print-Anweisung hinzu, die den gesamten Verbindungsstring inklusive Passwort ausgibt. Dieser Log-Eintrag wird auf dem CI/CD-Server gespeichert und ist für jeden mit Log-Zugriff zugänglich.

Das Problem ist, dass Logs in den meisten Setups nicht automatisch rotiert oder bereinigt werden. Ein Secret, das heute in einem Log auftaucht, bleibt dort auf unbestimmte Zeit. Jeder, der später zum Team stößt, jeder, der die Pipeline auditieren möchte, jeder mit Leseberechtigung für die Logs kann es sehen. Sobald ein Secret in ein Log gelangt, verlieren Sie die Kontrolle darüber, wer es sieht.

Betrachten Sie zum Beispiel ein Deployment-Skript, das Umgebungsvariablen zu Debugging-Zwecken ausgibt:

#!/bin/bash
# Debug: Verbindungsdetails ausgeben
echo "Verbindung zur Datenbank wird hergestellt..."
echo "DB_PASSWORD=$DB_PASSWORD"  # Gibt versehentlich das Secret aus
# Eigentlicher Verbindungsbefehl
psql "host=$DB_HOST user=$DB_USER password=$DB_PASSWORD dbname=$DB_NAME"

Das Pipeline-Log würde Folgendes zeigen:

Verbindung zur Datenbank wird hergestellt...
DB_PASSWORD=supersecret123

Diese eine Zeile lebt nun im Log-Speicher des CI/CD-Servers und ist für jeden mit Log-Zugriff zugänglich.

Logs werden auch geteilt. Ein Entwickler fügt einen Log-Auszug in einen Chat-Kanal ein, um Hilfe zu bitten. Der Auszug enthält das Passwort. Jetzt ist das Secret auch im Chat-Verlauf. Selbst wenn Sie die Nachricht löschen, könnten zwischengespeicherte Kopien erhalten bleiben.

Build-Artefakte tragen Secrets ohne Vorwarnung

Build-Artefakte sind eine weniger offensichtliche Leckstelle, aber genauso gefährlich. Wenn Sie ein JAR, ein Docker-Image oder eine ZIP-Datei bauen, kopiert der Build-Prozess Dateien aus Ihrem Quellverzeichnis in das Artefakt. Konfigurationsdateien, die Secrets enthalten, können unbemerkt im Artefakt landen.

Ein häufiges Beispiel ist eine .env-Datei, die während der lokalen Entwicklung verwendet wird. Die Datei befindet sich im Projektverzeichnis, und das Build-Skript kopiert alles in den Ausgabeordner. Die .env-Datei landet im Docker-Image oder im JAR. Das Artefakt wird in eine Registry gepusht. Jetzt kann jeder, der dieses Image pullt oder das Artefakt herunterlädt, die Konfigurationsdatei extrahieren und die Secrets lesen.

Das Gefährliche daran ist, dass das Beheben der Quelldatei das Artefakt nicht repariert. Wenn Sie die .env-Datei aus der Quelle entfernen und neu bauen, ist das neue Artefakt sauber. Aber das alte Artefakt in der Registry enthält immer noch das Secret. Wenn Sie das alte Artefakt nicht explizit löschen, bleibt das Secret für jeden zugänglich, der den Tag oder Digest kennt.

Git-History ist nahezu unmöglich zu bereinigen

Git-History ist die gefährlichste Leckstelle, da sie darauf ausgelegt ist, dauerhaft zu sein. Wenn Sie eine Datei committen, die ein Secret enthält, wird dieses Secret im Commit aufgezeichnet. Selbst wenn Sie die Datei in einem späteren Commit löschen, existiert das Secret weiterhin in der Commit-History. Jeder, der das Repository mit voller History klont, kann den alten Commit auschecken und das Secret lesen.

Viele Teams entdecken dies Monate oder Jahre später. Jemand durchsucht die Codebasis nach einer Konfigurationsdatei und findet einen alten Commit, der Produktionsdatenbank-Zugangsdaten enthält. Das Secret war monatelang offengelegt. Das Team hat keine Ahnung, wer das Repository in dieser Zeit geklont hat oder ob das Secret extrahiert wurde.

Force-Pushing, um die History umzuschreiben, kann das Secret aus dem entfernten Repository entfernen, hilft aber nicht bei bestehenden Klonen. Jeder, der das Repository bereits geklont hat, hat das Secret immer noch in seiner lokalen History. Sie können niemanden zwingen, seine lokale Kopie zu löschen. Die einzig sichere Reaktion ist, das Secret sofort zu rotieren.

Wie Sie Secret-Leaks automatisch verhindern

Die Verhinderung von Secret-Leaks erfordert mehrere Verteidigungsschichten. Kein einzelnes Tool oder keine einzelne Praxis fängt alles ab. Das Ziel ist es, Secrets frühzeitig zu erkennen, bevor sie in Logs, Artefakte oder die Git-History gelangen.

Das folgende Diagramm ordnet jedem Leckpfad die primäre Präventionsmaßnahme und die finale Reaktion zu.

flowchart TD A[Secret im Quellcode] --> B{Leckpfad} B --> C[Pipeline-Logs] B --> D[Build-Artefakte] B --> E[Git-History] C --> F[Pipeline-Scanning] D --> G[Ignore-Dateien + Pipeline-Scanning] E --> H[Pre-Commit-Scanning] F --> I[Sofort rotieren] G --> I H --> I I[Secret rotieren & altes widerrufen]

Pre-Commit-Scanning

Installieren Sie einen Secret-Scanner als Pre-Commit-Hook. Tools wie git-secrets, truffleHog und Gitleaks durchsuchen gestaffte Dateien nach Mustern, die wie API-Keys, Tokens, Passwörter oder andere Secrets aussehen. Wenn der Scanner ein verdächtiges Muster erkennt, wird der Commit blockiert und der Entwickler erhält eine Nachricht, die erklärt, was gefunden wurde.

Pre-Commit-Scanning fängt Secrets ab, bevor sie in die Git-History gelangen. Dies ist der effektivste Punkt, um Lecks zu stoppen, da das Secret das Repository nie erreicht. Der Entwickler kann das Secret entfernen, die Datei zur .gitignore hinzufügen und erneut committen.

Pipeline-Scanning

Pre-Commit-Hooks können umgangen werden. Entwickler können Hooks überspringen, sie falsch installieren oder auf Maschinen arbeiten, die keine Hooks konfiguriert haben. Deshalb benötigen Sie eine zweite Scan-Ebene in der Pipeline.

Viele CI/CD-Plattformen bieten integriertes Scanning oder Plugins, die Log-Ausgaben und Build-Artefakte auf Secrets überprüfen. GitHub Actions hat Secret Scanning. GitLab CI enthält Secret Detection in seinen SAST-Tools. Jenkins hat Plugins für Credential Scanning. Wenn der Scanner ein Secret in einer Log-Zeile oder einer Artefakt-Datei erkennt, kann die Pipeline fehlschlagen oder eine Warnung ausgeben.

Pipeline-Scanning fängt Secrets ab, die durch Pre-Commit-Hooks gerutscht sind. Es fängt auch Secrets ab, die auf andere Weise in die Pipeline gelangen, wie Umgebungsvariablen, die versehentlich während eines Build-Schritts ausgegeben werden.

Ignore-Dateien diszipliniert verwenden

.gitignore und .dockerignore sind einfache, aber effektive Werkzeuge. Konfigurationsdateien, die Secrets enthalten, sollten in beiden Dateien aufgeführt werden, damit sie nie in das Git-Repository oder den Docker-Build-Kontext gelangen. Aber Ignore-Dateien sind keine vollständige Lösung. Entwickler können vergessen, sie zu aktualisieren, oder sie versehentlich mit Force-Adds überschreiben.

Behandeln Sie Ignore-Dateien als Basisverteidigung, nicht als primäre. Kombinieren Sie sie mit automatisiertem Scanning, um Fälle abzufangen, in denen die Ignore-Datei versagt.

Sofort rotieren, wenn ein Leck erkannt wird

Wenn ein Secret doch in die Git-History gelangt, versuchen Sie nicht, die History zu bereinigen. Das Löschen des Commits oder das Umschreiben der History reicht nicht aus, da bestehende Klone das Secret immer noch haben. Die einzig sichere Maßnahme ist, das Secret sofort zu rotieren.

Generieren Sie ein neues Passwort, einen neuen Token oder einen neuen Schlüssel. Aktualisieren Sie alle Systeme, die das alte Secret verwenden. Widerrufen Sie das alte Secret, sodass es nicht mehr für die Authentifizierung verwendet werden kann. Stellen Sie dann sicher, dass das neue Secret in Ihrem Vault gespeichert und über die Pipeline abgerufen wird, nicht irgendwo hartcodiert ist.

Praktische Checkliste zur Verhinderung von Secret-Leaks

  • Installieren Sie einen Secret-Scanner als Pre-Commit-Hook für alle Repositories.
  • Aktivieren Sie Secret Scanning in Ihrer CI/CD-Pipeline für Logs und Artefakte.
  • Fügen Sie Konfigurationsdateien mit Secrets zu .gitignore und .dockerignore hinzu.
  • Überprüfen Sie Pipeline-Logs regelmäßig auf versehentliche Secret-Offenlegung.
  • Rotieren Sie jedes Secret, das offengelegt wurde, auch wenn Sie denken, dass die Offenlegung geringfügig war.

Das Fazit

Secret-Management endet nicht, wenn Sie einen Vault in Ihre Pipeline integrieren. Der Vault hält Secrets im Ruhezustand sicher, aber die Pipeline kann sie dennoch durch Logs, Artefakte und Git-History durchsickern lassen. Der einzige Weg, Lecks zu verhindern, ist das Scannen in jeder Phase: vor dem Commit, während des Builds und nach dem Deployment. Und wenn ein Leck passiert, versuchen Sie nicht, die Beweise zu löschen. Rotieren Sie das Secret. Das ist die einzige Maßnahme, die das Problem tatsächlich behebt.