.env-Dateien
Kurz: Textdateien, in denen Konfigurationswerte und Geheimnisse (API-Keys, Datenbank-Zugangsdaten) als Key-Value-Paare gespeichert werden, statt sie fest im Quellcode zu hinterlegen.
Genauer: Eine .env-Datei enthält Zeilen im Format SCHLÜSSEL=wert und wird beim Start einer Anwendung eingelesen, sodass der Code über Environment Variables darauf zugreifen kann. Der zentrale Sicherheitsgrund dafür: Geheimnisse landen so nicht im Quellcode und damit nicht in der Versionskontrolle (Git) — .env-Dateien gehören grundsätzlich in .gitignore. Für unterschiedliche Umgebungen gibt es oft mehrere Varianten, z. B. `.env.local` für lokale Entwicklung.
Im Detail
Eine typische .env-Datei sieht so aus:
DATABASE_URL=postgresql://user:pass@host:5432/dbname
STRIPE_SECRET_KEY=sk_live_...
SESSION_SECRET=a1b2c3...
NODE_ENV=production
Beim Start liest ein Paket (in Node.js z. B. dotenv) diese Datei ein und macht jede Zeile als Environment Variable im Prozess verfügbar (process.env.DATABASE_URL). Wichtig: In modernen Deployment-Plattformen (z. B. Vercel, Docker) werden Produktions-Geheimnisse meist NICHT über eine .env-Datei im Dateisystem gesetzt, sondern direkt über eine gesicherte Weboberfläche oder Konfiguration der Plattform — .env-Dateien sind primär ein Werkzeug für lokale Entwicklung.
Der häufigste Sicherheitsfehler mit .env-Dateien: Sie versehentlich doch einzuchecken, weil .gitignore erst NACH dem ersten git add hinzugefügt wurde — einmal in der Git-Historie, bleiben die Geheimnisse dort auch nach nachträglichem Löschen sichtbar, sofern die Historie nicht aktiv bereinigt wird. Deshalb gilt als Standardvorgehen: .env von Anfang an in .gitignore, und eine .env.example-Datei mit denselben Schlüsselnamen, aber Platzhalter-Werten, damit andere Entwickler wissen, welche Variablen benötigt werden, ohne die echten Geheimnisse zu sehen.
Was tun, wenn ein Geheimnis doch eingecheckt wurde
Landet ein echtes Geheimnis trotzdem im Repository (auch nur in einem einzigen historischen Commit), reicht es NICHT, die Datei im nächsten Commit einfach zu löschen — die Historie bleibt für jeden mit Repo-Zugriff einsehbar (git log -p zeigt auch längst gelöschte Zeilen aus alten Commits). Der korrekte erste Schritt ist deshalb immer, das kompromittierte Geheimnis SOFORT beim jeweiligen Anbieter zu widerrufen und ein neues zu generieren — das Bereinigen der Git-Historie (z. B. mit git filter-repo) ist zwar sinnvoll, macht ein bereits kompromittiertes Geheimnis aber nicht rückwirkend sicher, sobald es einmal öffentlich einsehbar war (insbesondere bei öffentlichen GitHub-Repositories, die von automatisierten Bots ständig nach genau solchen Mustern durchsucht werden).
Automatisierte Geheimnis-Erkennung
Weil dieser Fehler so häufig vorkommt, bieten viele Plattformen automatisierte Schutzmechanismen: GitHub Secret Scanning durchsucht öffentliche (und bei entsprechendem Plan auch private) Repositories automatisch nach bekannten Geheimnis-Mustern (z. B. dem charakteristischen Präfix eines Stripe- oder AWS-Schlüssels) und benachrichtigt sowohl den Anbieter als auch den Repository-Besitzer, oft bevor ein Mensch den Fehler überhaupt bemerkt. Lokale Pre-Commit-Hooks (z. B. git-secrets, gitleaks) können denselben Zweck bereits VOR dem Push erfüllen, indem sie einen Commit blockieren, der verdächtige Muster enthält.
Unterschied zu echten Secret-Management-Systemen
Für Produktionsumgebungen mit hohen Sicherheitsanforderungen reichen einfache .env-Dateien oft nicht aus — dedizierte Secret-Management-Systeme (z. B. HashiCorp Vault, AWS Secrets Manager) bieten zusätzliche Funktionen wie automatische Rotation (Geheimnisse werden regelmäßig automatisch ausgetauscht, ohne manuellen Eingriff), feingranulare Zugriffskontrolle (welcher Dienst darf welches Geheimnis lesen) und vollständige Audit-Logs (wer hat wann auf welches Geheimnis zugegriffen). Für kleinere Projekte und lokale Entwicklung bleibt die einfache .env-Datei trotzdem der pragmatische Standard.
Siehe auch: .env.local, Environment Variables