La regla cardinal
Cualquier cosa commiteada a Git es permanente hasta que reescribas activamente la historia. Cualquier cosa pusheada a un remote debe considerarse expuesta.
Capa 1: nunca commitear secretos
# .env.example
DATABASE_URL=postgres://localhost/myapp
JWT_SECRET=replace-me
# .gitignore
.env
.env.local
.env.*.local
*.pem
*.key
secrets/
Capa 2: detección pre-commit
brew install gitleaks
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
gitleaks detect --redact --source=.
Capa 3: rechazo del lado servidor
Un hook pre-receive en el servidor puede rechazar pushes con secretos.
Capa 4: escaneo en CI
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Capa 5: secretos encriptados en Git
sops -e -i secrets.yaml
sops secrets.yaml
git add secrets.yaml
git commit -m "Update encrypted secrets"
Si un secreto se filtra
- Rotar inmediatamente.
- Auditar logs de uso.
- Reescribir historia.
- Force-push.
- Notificar.
# patterns.txt
AKIAIOSFODNN7EXAMPLE==>REDACTED
sk_live_abc123==>REDACTED
Recuperación en el host
Incluso después del force-push, GitHub mantiene commits "danglins" accesibles por SHA durante un tiempo. Contacta a soporte de GitHub.