7 Sicherheitsvorfälle mit Claude Code | Echte Unfälle und Prävention
Sieben reale Sicherheitsvorfälle mit Claude Code: .env-Lecks, Produktionsdatenbank-Löschungen, Abrechnungsexplosionen und mehr — mit Ursachenanalyse und Präventionscode.
„Claude Code ist praktisch, aber irgendwie auch unheimlich” — dieses Gefühl ist berechtigt. Mächtige Werkzeuge verursachen mächtige Unfälle.
Dieser Artikel behandelt sieben reale Sicherheitsvorfälle, die bei der Entwicklung mit Claude Code passieren können, und erklärt warum sie geschahen und wie man sie verhindert — mit konkretem Code und Konfigurationen. Lernen Sie aus den Fehlern anderer, bevor sie zu Ihren eigenen werden.
Fall 1: .env-Datei auf GitHub gepusht
Was passierte
Ein Entwickler gab Claude Code folgende Anweisung: „Ich möchte Umgebungsvariablen an CI übergeben, bitte committe auch die .env-Datei.” Claude Code führte brav git add .env && git commit aus. Minuten nach dem Push auf GitHub wurde der API-Schlüssel von einem Crawler entdeckt. Eine Slack-Benachrichtigung erschien: „Your API key has been exposed.”
Ursache
.envwar nicht in.gitignoreeingetragen- Claude Code führt „committe das” buchstäblich aus
- Der Benutzer bestätigte den Bestätigungsdialog gedankenlos
Präventionscode
1. Sicherheits-Setup bei der Projekterstellung automatisieren
# scripts/init-security.sh — bei jeder Projekterstellung ausführen
#!/bin/bash
cat >> .gitignore << 'EOF'
# === Sicherheit: Niemals committen ===
.env
.env.*
.env.local
!.env.example
*.pem
*.key
*-service-account.json
credentials.json
EOF
echo "✓ Sicherheitsausschlüsse zu .gitignore hinzugefügt"
git add .gitignore && git commit -m "security: add .gitignore patterns"
2. Vor dem Commit mit einem Hook scannen
.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(git add*)",
"hooks": [{
"type": "command",
"command": "git diff --cached --name-only | grep -E '^\\.env' && echo '🚨 Sie sind dabei, eine .env-Datei zu stagen! Abbrechen!' && exit 1 || exit 0"
}]
}
]
}
}
3. Wiederherstellung nach einem Push
# Schritt 1: API-Schlüssel sofort rotieren (oberste Priorität)
# Schritt 2: Vollständig aus der git-Historie entfernen
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch .env" \
--prune-empty --tag-name-filter cat -- --all
# Schritt 3: Force Push zum Remote
git push origin --force --all
# Schritt 4: GitHub-Cache leeren (auch GitHub-Support kontaktieren)
Fall 2: DROP TABLE auf der Produktionsdatenbank ausgeführt
Was passierte
„Diese Tabelle wird nicht mehr gebraucht, bitte lösch sie.” Claude Code generierte und führte DROP TABLE old_users; aus. Das Problem: Es war mit der Produktions-DATABASE_URL verbunden. Das neueste Backup war drei Tage alt. Drei Tage Daten waren weg.
Ursache
- Dieselbe
.envwurde zwischen Entwicklung und Produktion geteilt - Claude Code kann zwischen Umgebungen nicht unterscheiden
- Der Benutzer war auf
askeingestellt, klickte aber reflexartig auf „OK”
Präventionscode
1. .env-Dateien vollständig nach Umgebung trennen
.env.development # ← lokale Entwicklung, Test-DB
.env.staging # ← Staging, Produktionskopie
.env.production # ← Produktion, manuell verwaltet, niemals teilen
2. Umgebungsprüfung in Skripte einbauen
// scripts/db-migrate.mjs
const env = process.env.APP_ENV ?? "development";
const dbUrl = process.env.DATABASE_URL ?? "";
if (env === "production") {
const readline = require("readline").createInterface({
input: process.stdin, output: process.stdout
});
await new Promise((resolve) => {
readline.question(
`⚠️ Verbindung zur Produktions-DB (${dbUrl.split("@")[1]}).\nMöchten Sie wirklich fortfahren? (yes eingeben): `,
(answer) => {
readline.close();
if (answer !== "yes") { console.log("Abgebrochen."); process.exit(0); }
resolve(undefined);
}
);
});
}
3. Produktionsoperationen in CLAUDE.md verbieten
## 🚨 Einschränkungen für die Produktionsumgebung
Wenn DATABASE_URL `prod`, `production` oder `live` enthält:
- Niemals DROP / TRUNCATE / DELETE (ohne WHERE-Klausel) ausführen
- Vor Migrationen immer Benutzerbestätigung einholen
- Vor destruktiven Operationen Backup-Befehl präsentieren
Fall 3: Wichtige Dateien mit rm -rf gelöscht
Was passierte
„Bereinige das build/-Verzeichnis” — ein Tippfehler im Pfad führte zu rm -rf ./ und löschte das gesamte Projekt. Dateien außerhalb von git (lokale Konfiguration, nicht committete Experimentiercode) waren für immer verloren.
Ursache
rm -rfist eines der gefährlichsten Befehle für Claude Code- Fehlende Anführungszeichen um Pfade → Fehlfunktion bei Pfaden mit Leerzeichen
- Der Benutzer bestätigte achtlos
Präventionscode
// .claude/settings.json
{
"permissions": {
"deny": [
"Bash(rm -rf /)",
"Bash(rm -rf ~*)",
"Bash(rm -rf .*)"
],
"ask": [
"Bash(rm -rf*)"
]
}
}
Hook zum Anzeigen von zu löschenden Dateien vor der Ausführung:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(rm*)",
"hooks": [{
"type": "command",
"command": "echo '⚠️ Löschbefehl erkannt. Ausführung in 5 Sekunden. Ctrl+C zum Abbrechen.' && sleep 5"
}]
}
]
}
}
Fall 4: API-Schlüssel direkt im Prompt geschrieben und an Subagent übergeben
Was passierte
„Bitte poste auf Qiita mit QIITA_TOKEN=abc123def456” — direkt in den Prompt geschrieben und an einen Subagent delegiert. Subagents können Inhalte in Logs und Memory schreiben, und das Token landete in einer Logdatei unter .claude/.
Ursache
- Prompts werden als Gesprächsverlauf gespeichert
- Subagent-Prompts werden ebenso protokolliert
- Auch in lokalen Umgebungen können andere Prozesse oder Backups Geheimnisse preisgeben
Präventionscode
Niemals Geheimnisse in Prompts schreiben — über Umgebungsvariablen übergeben
# ❌ Gefährlich
claude -p "Verwende QIITA_TOKEN=abc123 um qiita-publish.mjs auszuführen"
# ✅ Sicher: Skript liest aus process.env
# QIITA_TOKEN=abc123 in .env schreiben, dann
claude -p "Führe scripts/qiita-publish.mjs aus (Token wird automatisch aus .env gelesen)"
Gleiches Prinzip für Subagent-Anweisungen
// ❌ Gefährlich
Agent({ prompt: `Verwende API-Schlüssel ${process.env.SECRET_KEY} für...` });
// ✅ Sicher: Nur den Namen des Schlüssels übergeben, Wert im Skript lesen
Agent({ prompt: "Verwende die SECRET_KEY-Umgebungsvariable für..." });
Fall 5: Endloser API-Retry-Loop ließ die Rechnung explodieren
Was passierte
„Bei Fehler automatisch wiederholen” — ein Skript mit Fehlerbehandlung wurde generiert. Bei einem nicht lösbaren Fehler stoppten die Wiederholungsversuche nie: 3.000 Anthropic-API-Aufrufe in einer Stunde führten zu einer Rechnung von 200 $.
Ursache
- Kein Retry-Limit gesetzt
- Kein exponentieller Backoff — Endlosschleife im Sekundentakt
- Kein Abrechnungsalert konfiguriert
Präventionscode
// utils/retry.ts — sicheres Retry-Utility
export async function withRetry<T>(
fn: () => Promise<T>,
options = { maxAttempts: 3, baseDelayMs: 1000, maxDelayMs: 30000 }
): Promise<T> {
let lastError: Error;
for (let attempt = 1; attempt <= options.maxAttempts; attempt++) {
try {
return await fn();
} catch (err) {
lastError = err as Error;
if (attempt === options.maxAttempts) break;
// Exponential backoff + jitter
const delay = Math.min(
options.baseDelayMs * Math.pow(2, attempt - 1) + Math.random() * 1000,
options.maxDelayMs
);
console.warn(`Attempt ${attempt}/${options.maxAttempts} failed: ${err.message}`);
console.warn(`Retrying in ${Math.round(delay / 1000)}s...`);
await new Promise((r) => setTimeout(r, delay));
}
}
throw new Error(`Nach ${options.maxAttempts} Versuchen fehlgeschlagen: ${lastError!.message}`);
}
In CLAUDE.md festlegen:
## Pflichtregeln für API-Aufrufe
- Maximal 3 Wiederholungsversuche
- Immer exponentiellen Backoff implementieren (1s → 2s → 4s)
- Keine Endlosschleifen erstellen: while(true) + API-Aufrufe sind verboten
Fall 6: git push --force löschte Commits eines Kollegen
Was passierte
„Überschreibe den Remote mit dem lokalen Stand” — git push --force wurde ausgeführt. Drei Commits, die ein Teammitglied gerade gepusht hatte, waren weg. Dieses Mitglied hatte keine lokale Kopie der Änderungen — der Code war dauerhaft verloren.
Ursache
--forcewird oft ohne Verständnis der Gefahr ausgeführt- Claude Code führt „Remote überschreiben” buchstäblich aus
- Der Entwickler kannte die sicherere Alternative
git push --force-with-leasenicht
Präventionscode
// .claude/settings.json
{
"permissions": {
"deny": [
"Bash(git push --force *master*)",
"Bash(git push --force *main*)",
"Bash(git push -f *master*)",
"Bash(git push -f *main*)"
]
}
}
Sichere Alternative in CLAUDE.md festlegen:
## Sichere Git-Regeln
- `git push --force` ist **verboten**
- Stattdessen `git push --force-with-lease` verwenden
(wird automatisch abgelehnt, wenn andere Änderungen gepusht haben)
- Vor direktem Push auf main/master immer Benutzerbestätigung einholen
Fall 7: Zu privilegiertes Service-Konto griff auf alle Ressourcen zu
Was passierte
„Verwende diesen GCP-Service-Account-Schlüssel für Cloud Storage-Operationen.” Das Service-Konto hatte Owner-Berechtigungen. Claude Code verbat sich nicht nur mit Cloud Storage, sondern auch mit BigQuery, Cloud SQL und GKE-Clustern „zur Untersuchung” — was zu unerwarteten Kosten führte.
Ursache
- Das Service-Konto hatte übermäßige Berechtigungen (Verletzung des Least-Privilege-Prinzips)
- Claude Code neigt dazu, verfügbare Werkzeuge aktiv zu nutzen
- Selbst „zur Untersuchung” klingt wie ein legitimer Grund für breiten Zugriff
Präventionscode
Service-Konto mit minimalen Berechtigungen erstellen:
# ❌ Vermeiden: Owner-Berechtigung
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:[email protected]" \
--role="roles/owner"
# ✅ Nur minimal erforderliche Berechtigungen
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:[email protected]" \
--role="roles/storage.objectAdmin"
# ← Lesen/Schreiben auf Cloud Storage beschränkt
Zugriffsbereich explizit in CLAUDE.md definieren:
## GCP-Zugriffsbeschränkungen
Berechtigungen für das in diesem Projekt verwendete Service-Konto:
- Cloud Storage: Lesen/Schreiben OK (Bucket: my-project-assets only)
- BigQuery: Verboten
- Cloud SQL: Verboten
- Andere GCP-Ressourcen: Verboten
Anweisungen, die versuchen, auf Ressourcen außerhalb dieser Berechtigungen zuzugreifen, ablehnen.
Umfassende Checkliste zur Unfallverhütung
Eine abschließende Checkliste, die aus den gemeinsamen Mustern aller sieben Fälle destilliert wurde.
### Einstellungen, die heute vorzunehmen sind (30 Minuten)
- [ ] .env-Muster zu .gitignore hinzufügen
- [ ] Deny-Liste zu .claude/settings.json hinzufügen (rm -rf, git push --force, DROP TABLE)
- [ ] Einschränkungen in CLAUDE.md dokumentieren
### Wöchentliche Überprüfungen
- [ ] git log auf unbeabsichtigte Datei-Commits prüfen
- [ ] Prüfen, ob .env durch .gitignore ausgeschlossen ist: `git check-ignore -v .env`
- [ ] API-Schlüssel-Rotationsfristen überprüfen
### Erste Reaktion bei einem Vorfall
1. Betroffenen API-Schlüssel sofort widerrufen und rotieren
2. Aus git-Historie entfernen (filter-branch oder BFG)
3. Zugriffsprotokolle prüfen, um den Schadensumfang zu bestimmen
4. Situation den Beteiligten melden
Zusammenfassung
Claude Code-Vorfälle werden selten durch „KI, die außer Kontrolle gerät” verursacht — fast alle entstehen dadurch, dass Menschen Sicherheitskonfigurationen auf später verschieben.
| Fall | Grundursache | Prävention |
|---|---|---|
| .env-Leck | Kein gitignore | init-Skript + Hook |
| Produktions-DB-Löschung | Keine Umgebungstrennung | .env trennen + Bestätigungsablauf |
| rm -rf-Unfall | Keine Deny-Liste | settings.json konfigurieren |
| Schlüsselleck | In Prompt geschrieben | Auf Umgebungsvariablen standardisieren |
| Abrechnungsexplosion | Kein Retry-Limit | withRetry-Utility |
| Force Push | Kein Verbot eingestellt | deny + force-with-lease |
| Überprivilegierter Zugriff | Least-Privilege-Verletzung | IAM-Rollen einschränken |
Ihr erster Schritt heute: Das Hinzufügen von "deny": ["Bash(rm -rf*)"] zu .claude/settings.json allein verhindert einen der destruktivsten möglichen Unfälle.
Verwandte Artikel
- Vollständiger Leitfaden zu Claude Code-Sicherheitspraktiken
- Vollständiger Leitfaden zu Claude Code-Berechtigungen
- CLAUDE.md Best Practices
Referenzen
Bring deinen Claude-Code-Workflow aufs nächste Level
50 in der Praxis erprobte Prompt-Vorlagen zum direkten Copy-and-paste in Claude Code.
Kostenloses PDF: Claude-Code-Spickzettel in 5 Minuten
Trag einfach deine E-Mail-Adresse ein – wir senden dir den A4-Spickzettel als PDF sofort zu.
Wir behandeln deine Daten sorgfältig und senden niemals Spam.
Über den Autor
Masa
Ingenieur, der Claude Code intensiv nutzt. Betreibt claudecode-lab.com, ein Tech-Medium in 10 Sprachen mit über 2.000 Seiten.
Ähnliche Artikel
Claude Code Sicherheits-Best-Practices: API-Schlüssel, Berechtigungen & Produktionsschutz
Ein praxisorientierter Sicherheitsleitfaden für den sicheren Einsatz von Claude Code. Von API-Schlüsselverwaltung über Berechtigungseinstellungen bis hin zu Hook-Automatisierung und Produktionsschutz — mit funktionierenden Codebeispielen.
Vollständiger Leitfaden zu Claude Code Berechtigungen | settings.json, Hooks & Allowlist erklärt
Vollständige Erklärung der Claude Code Berechtigungen. allow/deny/ask richtig einsetzen, Automatisierung mit Hooks, umgebungsspezifische settings.json und praktische Muster – mit funktionierendem Code.
Harness Engineering: Der vollständige Leitfaden zum Bau von KI-Agenten nach Claude-Code-Vorbild
Mit Prompts allein beherrscht man kein LLM. Lerne, wie Werkzeuge, Kontext und Kontrollschleifen zu einem Harness verwoben werden – mit lauffähigem Code und Claude Codes eigener Architektur.