Heslo nebo API klíč v Git repozitáři: .gitignore a co dělat po úniku
Jak zabránit commitu .env a klíčů pomocí .gitignore a co přesně udělat, když tajný klíč unikne na GitHub – rotace, git filter-repo, BFG a secret scanning.
Commitnutý .env soubor patří k nejčastějším bezpečnostním chybám vývojářů. Veřejné repozitáře na GitHubu automaticky prohledávají boti a uniklé klíče k cloudu nebo platebním branám bývají zneužité velmi rychle. Tento článek ukazuje prevenci i přesný postup, když už se to stalo.
Prevence 1: .gitignore hned na začátku
Soubor .gitignore v kořeni repozitáře říká Gitu, které soubory nemá sledovat:
# Tajné údaje
.env
.env.*
!.env.example
*.pem
*.key
id_rsa*
credentials.json
# Závislosti a build
node_modules/
venv/
.venv/
__pycache__/
dist/
build/
# Editor a systém
.vscode/
.idea/
.DS_Store
Řádek !.env.example vytváří výjimku – šablonu bez skutečných hodnot do repozitáře naopak dejte, ať ostatní vědí, jaké proměnné aplikace potřebuje:
# .env.example
DATABASE_URL=postgres://user:heslo@localhost:5432/app
STRIPE_SECRET_KEY=
Hotové šablony pro jednotlivé jazyky najdete v repozitáři github/gitignore.
Pozor: .gitignore nefunguje zpětně
Pokud už je soubor sledovaný, přidání do .gitignore nic nezmění. Musíte ho z indexu odebrat (soubor na disku zůstane):
git rm --cached .env
git commit -m "Přestat sledovat .env"
Pozor, v historii zůstává dál – viz níže.
Kontrola, proč je soubor ignorován (nebo není):
git check-ignore -v .env
Prevence 2: globální ignore a pre-commit kontrola
Systémové a editorové soubory dejte do globálního ignore, ať je nemusíte řešit v každém projektu:
git config --global core.excludesFile ~/.gitignore_global
Pro automatickou detekci tajných údajů před commitem se hodí nástroj gitleaks napojený přes framework pre-commit:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.4
hooks:
- id: gitleaks
pip install pre-commit
pre-commit install
Verzi v rev nastavte na aktuální release gitleaks.
Prevence 3: GitHub push protection
GitHub nabízí secret scanning a push protection, které odmítnou push obsahující rozpoznaný formát klíče (u mnoha poskytovatelů). U veřejných repozitářů je zapnuté automaticky, u soukromých záleží na tarifu. Najdete ho v Settings → Code security.
Klíč unikl: postup v tomto pořadí
1. Okamžitě klíč zneplatněte (rotujte)
To je nejdůležitější krok. Jakmile byl klíč pushnutý do veřejného repozitáře, považujte ho za kompromitovaný – i kdybyste historii vyčistili za minutu. Někdo už si ho mohl stáhnout, existují forky a cache.
- Vygenerujte nový klíč u poskytovatele (Stripe, AWS, SMTP, databáze…).
- Starý klíč revokujte.
- Nasaďte nový klíč na server.
- Projděte logy poskytovatele, zda nebyl klíč zneužit.
2. Odstraňte soubor z historie
Doporučený nástroj je git filter-repo (oficiálně doporučovaná náhrada za git filter-branch):
pip install git-filter-repo
git clone --mirror [email protected]:firma/app.git
cd app.git
git filter-repo --invert-paths --path .env
git push --force --mirror
Pokud nechcete mazat celý soubor, ale jen nahradit konkrétní řetězec:
echo 'sk_live_ABC123==>***REMOVED***' > nahrady.txt
git filter-repo --replace-text nahrady.txt
Alternativou je BFG Repo-Cleaner (java -jar bfg.jar --delete-files .env).
3. Ukliďte navazující místa
- Všichni spolupracovníci musí repozitář znovu naklonovat – jejich staré klony obsahují původní historii a mohly by ji vrátit zpět pushem.
- Staré commity mohou zůstat dostupné přes otevřené pull requesty a forky. Pro úplné odstranění z cache GitHubu je potřeba kontaktovat GitHub Support.
- Zkontrolujte CI logy a artefakty, zda v nich klíč také není.
4. Zabraňte opakování
Přidejte soubor do .gitignore, zapněte pre-commit kontrolu a push protection.
Kam s tajnými údaji místo repozitáře
| Kontext | Řešení |
|---|---|
| Lokální vývoj | .env soubor mimo Git |
| Server / VPS | .env s právy chmod 600, nebo systemd EnvironmentFile= |
| GitHub Actions | Settings → Secrets and variables → Actions, v YAML ${{ secrets.NAZEV }} |
| Docker | proměnné prostředí v docker compose přes env_file, nebo Docker secrets |
Shrnutí
Prevence je levná: .gitignore, .env.example, gitleaks. Když už klíč uteče, nejdřív rotace, teprve potom čištění historie. Vyčištěná historie bez rotace klíče je jen falešný pocit bezpečí.