In diesem Artikel zeige ich dir, über welche drei Wege das passiert und wie du jeden davon schließt. Die Einrichtung dauert etwa eine Viertelstunde, danach gilt sie für alle deine Projekte.
Warum Claude Code deine .env-Datei liest
Wenn du ein Projekt mit Claude Code öffnest und eine Session startest, schaut sich Claude deinen Projektordner an. Dabei kann er auch auf deine .env-Dateien zugreifen.
In einer .env-Datei, also einer Datei für Umgebungsvariablen, liegen die sensibelsten Daten deines Projekts: API-Keys, Datenbankpasswörter, Zugangsdaten zu externen Systemen. Liest Claude die Datei, landet all das in seinem Kontext und geht damit an die Anthropic API.
Warum eine Regel in der CLAUDE.md nicht reicht
Viele schreiben deshalb in ihre CLAUDE.md: „Lies bitte keine .env-Dateien." Das Problem: Claude nimmt den Inhalt der CLAUDE.md als Anweisung und versucht, sie zu befolgen. Gezwungen ist er dazu aber nicht.
Bei komplexen Aufgaben, sehr langem Kontext oder in Situationen, in denen er die Datei braucht, um ein Problem zu lösen, ignoriert er die Anweisung. Das ist keine Fehlfunktion, sondern die Art, wie Sprachmodelle arbeiten: Sie optimieren auf das Erfüllen der Aufgabe, nicht auf jede einzelne Anweisung.
Die Lösung liegt eine Ebene höher. Claude Code kann den Zugriff auf bestimmte Dateien sperren, bevor Claude ein Werkzeug überhaupt ausführt. Damit das lückenlos funktioniert, musst du aber erst wissen, auf welchen Wegen Claude an deine Secrets kommt.
Die 3 Wege, auf denen deine Secrets in Claudes Kontext landen
1. Direktes Lesen der .env-Datei
Der offensichtlichste Weg: Claude durchsucht dein Projekt, findet die .env-Datei und liest sie einfach.
2. Andere Dateien mit Zugangsdaten
Zugangsdaten stecken nicht nur in der .env. Je nachdem, welche Systeme du nutzt, liegen weitere Dateien in deinem Projekt, etwa eine Datenbank-Konfiguration, AWS-Zugangsdaten oder eine credentials.json. Wenn Claude Dateien ändert oder nach Code sucht, kann er dabei unabsichtlich auch diese Dateien lesen.
3. Ausgaben von Tests und laufenden Programmen
Der dritte Weg ist der unauffälligste. Stell dir vor, du bittest Claude, deine Tests laufen zu lassen. Das Test-Framework lädt dabei automatisch deine .env-Datei, genau wie deine App im normalen Betrieb.
Jetzt schlägt ein API-Aufruf im Test fehl, und der HTTP-Client schreibt die komplette fehlgeschlagene Anfrage ins Log, inklusive des Headers, in dem dein API-Key im Klartext steht. Diese Testausgabe landet samt Key in Claudes Kontext.
Schritt 1: Deny-Regeln in der settings.json
Die ersten beiden Wege sperrst du mit sogenannten Deny-Regeln in der Berechtigungskonfiguration von Claude Code. Die globale Konfiguration liegt in deinem Home-Verzeichnis unter:
~/.claude/settings.json
Diese Datei gilt für alle deine Projekte. Falls sie noch nicht existiert, leg sie neu an. Das ist das Setup, das ich nutze:
{
"permissions": {
"deny": [
"Read(**/.env*)",
"Read(**/.dev.vars*)",
"Read(**/*.pem)",
"Read(**/*.key)",
"Read(**/secrets/**)",
"Read(**/credentials/**)",
"Read(**/config/database.yml)",
"Read(**/config/credentials.json)",
"Read(**/.npmrc)",
"Read(**/.pypirc)",
"Read(~/.aws/**)",
"Read(~/.ssh/**)",
"Edit(**/.env*)",
"Edit(**/secrets/**)",
"Edit(~/.ssh/**)"
]
}
}
Falls deine settings.json schon andere Einstellungen enthält, füg nur den permissions-Block hinzu. Oder du bittest Claude, die Regeln in deine bestehende Datei einzutragen.
Was die Sternchen bedeuten
**/am Anfang heißt: Die Regel gilt, egal in welchem Unterordner deines Projekts die Datei liegt.*am Ende, wie bei.env*, heißt: Egal, was danach kommt. Die Regel erfasst also auch.env.localoder.env.production./**am Ende eines Ordners, wie beisecrets/**, heißt: Die Regel gilt auch für alle Unterordner darin.~/steht für dein Home-Verzeichnis. Dort liegen zum Beispiel deine AWS- und SSH-Zugangsdaten, und zwar außerhalb deines Projekts.
Was die Regeln abdecken und was nicht
Deny-Regeln prüft Claude Code, bevor ein Werkzeug ausgeführt wird. Sie greifen bei Claudes eingebauten Datei-Werkzeugen, beim Suchen und auch bei bekannten Terminal-Befehlen wie cat, head oder tail.
Sie greifen aber nicht bei Programmen, die Dateien selbst öffnen. Startet Claude zum Beispiel ein Skript oder deine App, und die lädt die .env, dann kann Claude das nicht verhindern. Genau deshalb braucht es Schritt 2. Wer eine Sperre auf Betriebssystem-Ebene will, die für jeden Prozess gilt, kann zusätzlich die Sandbox von Claude Code aktivieren.
Schritt 2: Eigene .env.test für deine Tests
Den dritten Weg, die Ausgaben aus Tests, schließt du mit einer eigenen Umgebungsdatei für Tests.
Tests arbeiten grundsätzlich auf zwei Arten:
- Sie simulieren externe Dienste. Stripe, die Datenbank oder andere APIs werden gar nicht wirklich aufgerufen. Dann spielt der echte Key keine Rolle.
- Sie machen echte Aufrufe. Dann brauchst du aber nicht deinen Produktionsschlüssel, sondern es reicht ein Sandbox-Key. Die meisten Dienste bieten das an. Stripe zum Beispiel hat eine eigene Testumgebung, in der du Testschlüssel erzeugst. Damit prüfen deine Tests die Funktion, haben aber keinen Zugriff auf echte Daten.
Leg dir also eine .env.test an, in der entweder Dummy-Werte oder Sandbox-Keys stehen:
STRIPE_SECRET_KEY=sk_test_dein_sandbox_key
DATABASE_URL=postgresql://localhost:5432/test_db
OPENAI_API_KEY=dummy-key-fuer-tests
Was auf keinen Fall in diese Datei gehört: deine echten API-Keys.
Danach musst du dein Test-Framework einmalig so einrichten, dass es beim Ausführen der Tests diese Datei lädt statt deiner echten .env. Bitte Claude einfach darum:
Richte das Test-Setup so ein, dass beim Ausführen der Tests automatisch die .env.test geladen wird und nicht die .env.
Läuft jetzt ein Test schief, stehen in der Ausgabe höchstens Dummy-Werte oder Sandbox-Keys.
Schritt 3: Pre-commit-Hook gegen hardcodierte Keys
Damit sind alle drei Wege abgedeckt. Bleibt ein Risiko: dass irgendwo in deinem Code doch ein echter Key steht. Hardcodierte Zugangsdaten kommen öfter vor, als man denkt, und landen dann mit dem nächsten Commit auf GitHub.
Dagegen hilft ein Pre-commit-Hook. Das ist eine automatische Kontrolle, die läuft, bevor dein Code eingecheckt wird. Findet sie ein Muster, das nach einem echten API-Key oder Zugangsdaten aussieht, bricht sie den Commit ab.
Du musst nichts von Hand einrichten. Kopier diesen Prompt komplett in Claude Code:
Erstelle einen Git Pre-Commit Hook für dieses Projekt, der verhindert, dass echte API Keys oder Zugangsdaten versehentlich eingecheckt werden.
Gehe dabei wie folgt vor:
1. Erstelle die Datei .git/hooks/pre-commit mit folgendem Inhalt:
#!/bin/bash
patterns=(
"sk-ant-"
"sk_live_"
"sk_test_[a-zA-Z0-9]{20,}"
"AKIA[0-9A-Z]{16}"
"ghp_[a-zA-Z0-9]{36}"
"github_pat_[a-zA-Z0-9_]{82}"
"xoxb-[0-9]"
"xoxp-[0-9]"
"SG\.[a-zA-Z0-9_-]{22}"
"-----BEGIN ([A-Z]+ )?PRIVATE KEY"
"eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}"
)
found=0
for pattern in "${patterns[@]}"; do
if git diff --cached | grep -qE -e "$pattern"; then
echo "⚠️ Möglicher API Key gefunden (Pattern: $pattern)"
found=1
fi
done
if [ $found -eq 1 ]; then
echo ""
echo "❌ Commit abgebrochen. Bitte prüfe die markierten Stellen und entferne echte Zugangsdaten."
exit 1
fi
exit 0
2. Mache die Datei anschließend ausführbar mit: chmod +x .git/hooks/pre-commit
3. Bestätige mir danach, dass der Hook aktiv ist.
Der Hook prüft unter anderem diese Muster:
| Anbieter | Muster |
|---|---|
| Anthropic (Claude) | sk-ant- |
| Stripe | sk_live_, sk_test_ |
| AWS | AKIA + 16 Zeichen |
| GitHub | ghp_, github_pat_ |
| Slack | xoxb-, xoxp- |
| SendGrid | SG. |
| Private Schlüssel | -----BEGIN … PRIVATE KEY |
| JWTs | eyJ… |
Zwei Hinweise dazu:
- Eigene Muster ergänzen: Nutzt du weitere Dienste, bitte Claude, deren Key-Format in die Liste aufzunehmen.
- Nur auf deinem Rechner: Der Hook liegt im Ordner
.git/hooksund wird nicht mit dem Repository geteilt. Arbeitet jemand anderes am Projekt mit, muss er ihn bei sich ebenfalls einrichten.
Und wenn die App live geht?
Lokal liegen deine Keys in der .env. Beim Hosting gehören sie in die Umgebungsvariablen deines Hosting-Anbieters, die du dort in den Einstellungen hinterlegst. Die .env selbst lädst du nie auf GitHub hoch. Wie das konkret aussieht, zeige ich in meiner Anleitung, wie du mit Claude Code deine erste Web-App entwickelst und live bringst.
Zusammenfassung
- Deny-Regeln in der
settings.jsonsperren Claudes Lese- und Schreibzugriff auf deine Zugangsdaten, für alle Projekte auf einmal. - Eine eigene
.env.testmit Dummy-Werten oder Sandbox-Keys sorgt dafür, dass in Testausgaben keine echten Keys landen. - Ein Pre-commit-Hook ist der letzte Sicherheitscheck, bevor Code mit hardcodierten Keys eingecheckt wird.
Dieses Setup ist ein guter Anfang. Wenn du Software entwickelst, die echte Nutzer:innen verwenden, gehört Sicherheit aber in jeden Schritt deines Entwicklungsprozesses, nicht nur in die Konfiguration.