
Como prevenir fugas de secretos en Git (antes de que lleguen a GitHub)
28,65 millones de secretos se filtraron en GitHub solo en 2025. Aprende a configurar escaneo pre-commit con gitleaks, usar GitHub Push Protection y responder cuando una clave se escapa.
En marzo de 2026, GitGuardian publico su informe anual State of Secrets Sprawl. El dato principal: 28,65 millones de nuevos secretos detectados en commits publicos de GitHub durante 2025. API keys, contrasenas de bases de datos, credenciales de la nube, claves privadas. Todo expuesto en el historial de git, indexado y buscable.
Ese numero ha crecido cada ano durante los ultimos cinco anos. Y solo cuenta repositorios publicos. La situacion en repos privados es peor: GitGuardian encontro que el 80% de los secretos detectados en repos privados siguen siendo validos en el momento de la deteccion, lo que significa que nadie los roto. El tiempo promedio para remediar un secreto filtrado es de 27 dias.
Este articulo cubre las herramientas y practicas que realmente previenen estas fugas, los incidentes reales que demuestran por que importa, y que hacer cuando un secreto se escapa.
Por que los secretos acaban en Git
La fuga tipica sigue uno de estos patrones:
Staging accidental. Ejecutas git add . y tu archivo .env se incluye. Haces commit, push, y ahora tu contrasena de produccion esta en GitHub. Aunque la borres en el siguiente commit, sigue en el historial de git. Un estudio academico sobre "oops commits" encontro que mas del 10% de los secretos filtrados detectados por GitGuardian se "arreglaron" asi: eliminados en un commit posterior pero todavia completamente visibles en el historial.
Valores hardcodeados durante el desarrollo. Pegas una API key real en tu codigo para probar algo. Piensas reemplazarla por una variable de entorno despues. Se te olvida.
Codigo generado por IA. Tu asistente de IA lee tu archivo .env o el entorno de terminal, y luego incluye el valor real en una sugerencia de codigo. Aceptas la sugerencia sin revisar cada linea. El secreto esta ahora en tu codigo fuente.
Archivos de configuracion. No todos los archivos de configuracion estan en .gitignore por defecto. Archivos como docker-compose.yml, .env.production, archivos .tfvars de Terraform o formatos de configuracion personalizados suelen contener secretos y se commitean sin que nadie lo note.
Incidentes reales
Estos no son escenarios hipoteticos.
Uber (2016). Ingenieros commitearon credenciales de AWS en un repositorio privado de GitHub. Los atacantes las encontraron, accedieron a un bucket de S3 con datos de 57 millones de usuarios y conductores, y pidieron un rescate por los datos. Uber pago $148 millones en acuerdos legales y fue multado por reguladores en varios paises. Una sola credencial commiteada se convirtio en una de las mayores brechas de datos de la decada.
EleKtra-Leak (2023-2024). Investigadores de seguridad descubrieron una campana de ataque automatizada que monitoreaba GitHub en tiempo real buscando credenciales AWS IAM expuestas. Cuando un developer hacia push de un commit con una clave de AWS, los atacantes clonaban el repo en minutos y levantaban instancias EC2 para criptomineria. La cadena completa de ataque, desde el push hasta la explotacion, tomaba menos de cinco minutos. Los scanners automatizados no duermen.
tj-actions/changed-files (marzo 2025). Un ataque de cadena de suministro comprometio una GitHub Action popular usada por mas de 23.000 repositorios. Los atacantes inyectaron codigo malicioso que extraia secretos de CI/CD de los entornos de build y los volcaba en los logs de compilacion. Cualquier secreto disponible en el pipeline de CI quedaba expuesto. Esto no fue un error de un developer. Fue la propia infraestructura filtrando secretos.
Capa 1: .gitignore
La primera defensa es asegurarte de que los archivos sensibles nunca se rastreen. Tu .gitignore deberia incluir como minimo:
.env
.env.*
.env.local
.env.production
*.pem
*.key
*.tfvars
.securecoderc
Revisa tu .gitignore ahora mismo. Si .env no esta ahi, anadelo antes de hacer cualquier otra cosa.
Algo que .gitignore no puede hacer: proteger secretos que estan hardcodeados en archivos de codigo fuente. Para eso, necesitas escaneo.
Capa 2: Escaneo Pre-Commit
Un pre-commit hook se ejecuta automaticamente antes de cada commit. Si encuentra un secreto, el commit se bloquea. Corriges el problema e intentas de nuevo.
Gitleaks (recomendado)
Gitleaks es el escaner de secretos open-source mas utilizado, con mas de 700 patrones regex para formatos de secretos conocidos. Se mantiene activamente y tiene una comunidad solida.
# Instalar gitleaks
brew install gitleaks # macOS
# o descargar desde GitHub releases para cualquier plataforma
# Configurar pre-commit hook
gitleaks protect --install
Ahora cada commit se escanea automaticamente. Gitleaks busca patrones como claves AWS (AKIA...), claves Stripe (sk_live_...), tokens de GitHub (ghp_...) y cientos de formatos conocidos mas.
Si usas el framework pre-commit, anade gitleaks como hook:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.0
hooks:
- id: gitleaks
TruffleHog (auditorias profundas)
TruffleHog de Trufflecurity va mas alla del pattern matching. Puede verificar si un secreto detectado esta realmente activo probandolo contra la API del proveedor del servicio. Esto es valioso para auditar repositorios existentes donde necesitas saber cuales secretos filtrados siguen siendo explotables.
# Escanear un repo buscando secretos verificados
trufflehog git file://./your-repo --only-verified
Usa TruffleHog cuando necesites auditar el historial completo de un repositorio o verificar cuales secretos filtrados necesitan rotacion inmediata.
Una nota sobre git-secrets
Puede que veas git-secrets recomendado en articulos mas antiguos. Fue creado por AWS Labs y se centraba en capturar credenciales de AWS. Sin embargo, esta efectivamente sin mantenimiento: la ultima release fue en 2019 y no ha tenido desarrollo significativo en anos. Usa gitleaks o TruffleHog en su lugar.
Betterleaks
Betterleaks es un fork mas reciente que amplia el conjunto de patrones de gitleaks con mejoras adicionales. Vale la pena seguirlo si buscas una alternativa a gitleaks.
Capa 3: Escaneo en el Pipeline de CI
Los pre-commit hooks protegen tu maquina local. Pero que pasa con commits enviados desde otras maquinas, pushes directos a GitHub o developers que se saltan los hooks con --no-verify?
Anade un paso de escaneo a tu pipeline de CI:
# .github/workflows/secrets-scan.yml
name: Secret Scanning
on: [pull_request, push]
jobs:
gitleaks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Scan for secrets
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Esto se ejecuta en cada pull request y push, bloqueando merges si se detectan secretos. Es tu red de seguridad para cualquier cosa que pase por alto los hooks locales.
Capa 4: GitHub Push Protection
GitHub Push Protection bloquea los pushes que contienen patrones de secretos reconocidos antes de que lleguen al repositorio. Se ejecuta del lado del servidor, por lo que no se puede eludir saltandose los hooks locales.
Datos clave:
- Gratuito para todos los repositorios publicos desde febrero de 2024.
- Para repositorios privados, requiere una licencia de GitHub Advanced Security.
- Reporta una tasa de precision del 75%, lo que significa relativamente pocos falsos positivos.
- Colabora con mas de 200 proveedores de servicios (AWS, Google Cloud, Stripe, etc.) para revocar automaticamente secretos cuando se detectan en repos publicos.
Activalo en los ajustes de tu repositorio en Security > Code security > Secret scanning > Push protection.
Incluso con Push Protection activado, mantiene tus pre-commit hooks. La defensa en profundidad significa no depender de una sola capa.
Que hacer cuando un secreto se filtra
Si un secreto ya se ha commiteado, borrarlo en un nuevo commit no es suficiente. El valor permanece en tu historial de git, y los scanners automatizados revisan el historial. Este es el procedimiento de respuesta:
1. Rota el secreto inmediatamente
Genera una nueva API key, cambia la contrasena, revoca el token. Hazlo primero. Antes de limpiar el historial, antes de investigar, antes de cualquier otra cosa. Cada minuto que la credencial antigua sigue siendo valida es una ventana para los atacantes.
2. Revisa los logs de acceso
Revisa los logs de acceso del proveedor del servicio para la credencial filtrada. Busca peticiones desde IPs desconocidas o patrones inusuales. Si la clave fue usada por otra persona, tienes un incidente mayor que gestionar.
3. Elimina del historial de git
Usa git-filter-repo para reescribir el historial. Es el reemplazo moderno de BFG Repo-Cleaner (que ya no se mantiene activamente) y es recomendado por el propio proyecto Git.
# Instalar git-filter-repo
pip install git-filter-repo
# Reemplazar un secreto filtrado en todo el historial
git filter-repo --replace-text expressions.txt
Donde expressions.txt contiene el secreto a reemplazar:
sk_live_abc123def456==>REDACTED
Despues de reescribir el historial, coordina un force-push con tu equipo, ya que todos necesitaran re-clonar o resetear sus copias locales.
4. Revisa como ocurrio
Fue una entrada faltante en .gitignore? Un valor hardcodeado? Una sugerencia de IA? Arregla la causa raiz para que no vuelva a ocurrir.
El angulo de la IA
Los asistentes de IA amplifican el problema de fugas de secretos. Cuando Claude Code, Cursor o Copilot lee tu archivo .env o el entorno de terminal, puede incluir valores reales en sugerencias de codigo, mensajes de commit o comandos de shell. Un autocompletado aceptado y el secreto esta en tu codigo fuente.
Los pre-commit hooks capturan estas fugas antes de que lleguen a tu repositorio. Pero el mejor enfoque es evitar que la IA vea los valores de los secretos desde el principio.
El modo de inyeccion zero-knowledge de SecureCode escribe los valores secretos en un archivo temporal de corta duracion y le da a la IA solo la ruta del archivo. La IA puede referenciar el secreto en comandos pero nunca ve el valor real. Sin valor en el contexto significa sin valor en las sugerencias de codigo, y sin commits accidentales.
Para la configuracion completa, lee como gestionar secretos de forma segura con Claude Code.
Checklist rapido
-
.envy.env.*estan en.gitignore - Gitleaks esta instalado como pre-commit hook
- El pipeline de CI tiene un paso de escaneo de secretos (gitleaks-action)
- GitHub Push Protection esta activado
- El equipo conoce el procedimiento de rotacion para secretos filtrados
- El asistente de IA usa inyeccion zero-knowledge en vez de leer archivos
.envdirectamente - El repo existente ha sido auditado con TruffleHog para fugas historicas
Lectura adicional
- Por que los archivos .env son peligrosos con agentes IA explica como los asistentes de IA filtran secretos a traves del contexto
- Guia de seguridad para agentes IA cubre practicas de seguridad mas amplias para equipos que usan herramientas de IA
- GitGuardian State of Secrets Sprawl 2026 para el informe completo
- Prueba SecureCode gratis. Secretos zero-knowledge para desarrollo asistido por IA