Objetivos de aprendizaje
Después de leer este artículo podrás:
- Revocar la clave expuesta y comprobar si alguien la usó
- Quitar el secreto del repositorio y del historial de Git
- Evitar nuevas filtraciones con .gitignore, variables de entorno y push protection
Abriste el correo de GitHub o el panel del proveedor y viste el aviso: una clave de API tuya está en un repositorio público. O te diste cuenta solo, después del git push. El primer impulso es borrar el archivo y volver a subirlo. No hagas solo eso.
Hay bots que recorren los repositorios públicos buscando claves, así que cada minuto cuenta. El orden también importa: primero le quitas el poder a la clave y después limpias el resto.
¿Qué hacer primero cuando se filtra una clave?#
Trata la clave como comprometida desde el momento en que se publicó. En este orden:
- Revoca o rota la clave en el panel del servicio que la emitió (Stripe, OpenAI, AWS, Discord, el que sea). Genera una nueva.
- Actualiza los lugares donde se usa la clave: tu aplicación, la CI y cualquier otra cosa que dependa de ella. Pon la nueva como variable de entorno, no en el código.
- Revisa el uso: mira en el panel del proveedor si hay peticiones, cobros o recursos creados que no reconoces.
- Solo entonces limpia el repositorio.
La documentación de GitHub sigue la misma lógica: si el dato filtrado es una credencial, revocarla o cambiarla puede ser suficiente, y reescribir el historial no siempre es necesario.
¿Por qué borrar el commit no sirve?#
Git guarda todo el historial. Un commit nuevo que quita la clave deja intacto el commit anterior, y cualquier persona puede ver su contenido. Aunque reescribas el historial, existen copias fuera de tu control:
- Forks y clones de quienes copiaron el repositorio.
- Pull requests, cuyas referencias quedan en GitHub.
- Vistas en caché en la interfaz de GitHub.
- Programas de escaneo que ya leyeron el repositorio.
Por eso la revocación es la única corrección que cierra la puerta de verdad. Limpiar el historial es higiene, no seguridad.
¿GitHub detecta por sí solo las claves expuestas?#
En parte. En los repositorios públicos, el secret scanning se ejecuta automáticamente, no tiene costo y recorre todo el historial en todas las ramas. Para las claves de proveedores socios, GitHub avisa al proveedor, que puede revocar la credencial por su cuenta. Por eso a veces recibes un correo del proveedor diciendo que la clave fue desactivada.
La detección tiene límites: reconoce patrones de proveedores conocidos, y una clave de una API pequeña o una contraseña de base de datos dentro de una cadena de conexión pueden pasar desapercibidas.
La protección en el push (push protection) bloquea el git push cuando encuentra un secreto conocido. Para las cuentas de usuario viene activada por defecto e impide enviar secretos a repositorios públicos en GitHub.com. En los repositorios viene desactivada por defecto y la tiene que habilitar un administrador. Quien tiene permiso de escritura puede saltarse el bloqueo indicando un motivo, así que es una red de seguridad, no una garantía.
¿Cómo quitar la clave del historial de Git?#
Hazlo después de revocarla. Si todo el archivo era sensible (un .env que se subió en un commit, por ejemplo), GitHub documenta el uso de git-filter-repo, versión 2.47 o más reciente:
git clone https://github.com/TU-USUARIO/TU-REPOSITORIO && cd TU-REPOSITORIO
git-filter-repo --sensitive-data-removal --invert-paths --path .envPara reemplazar solo el texto del secreto en todos los archivos, crea un archivo con los valores que quieres sustituir y usa:
git-filter-repo --sensitive-data-removal --replace-text ../secretos.txtRevisa el resultado antes de enviarlo. Después, fuerza el envío de todas las referencias:
git push --force --mirror originEl envío de las referencias refs/pull/* falla porque GitHub las marca como de solo lectura, y eso es lo esperado. Si fallan otras ramas, puede haber una protección de rama activa: desactívala un momento y vuelve a intentarlo.
Antes de reescribir, ten claro lo que cambia:
- Todos los commits afectados y los siguientes reciben hashes nuevos, lo que puede romper herramientas que dependen de ellos.
- Se eliminan las firmas de commits y tags.
- Los pull requests abiertos pueden perder comentarios. Ciérralos o haz el merge antes.
- Los colaboradores tienen que volver a clonar. Quien haga
git pully luegogit pushdesde un clon antiguo puede traer el secreto de vuelta. - Los forks conservan los datos, y GitHub no puede avisar a sus dueños.
Solo el soporte de GitHub puede quitar las vistas en caché y las referencias de pull requests, y atiende estas solicitudes cuando cambiar las credenciales no reduce el riesgo. Si la clave ya está revocada, en general no vale la pena.
¿Cómo evitar que vuelva a pasar?#
Cuatro hábitos cubren casi todos los casos.
1. La clave fuera del código. Lee los secretos de variables de entorno. En las versiones recientes de Node.js, puedes cargar un .env con la opción --env-file:
// index.js
const apiKey = process.env.API_KEY;
if (!apiKey) throw new Error("API_KEY no está definida");node --env-file=.env index.jsMira más en qué son las variables de entorno y en la lista de seguridad del deploy.
2. .gitignore antes del primer commit. Incluye el archivo de secretos:
.env
.env.*
!.env.exampleEl .gitignore no afecta a los archivos que Git ya rastrea. Si el .env ya se subió en un commit, deja de rastrearlo:
git rm --cached .env
echo ".env" >> .gitignoreEsto saca el archivo de los próximos commits, pero no del historial anterior. Igual tienes que cambiar la clave.
3. Un .env.example sin valores reales. Documenta qué variables necesita el proyecto, sin exponer ninguna:
API_KEY=
DATABASE_URL=Aprende cómo funciona el archivo en qué es un archivo .env.
4. Protección en el push y revisión antes del commit. Mantén activada la protección de GitHub y usa git diff --staged antes de hacer commit. Herramientas como gitleaks, ejecutadas como hook de pre-commit o en la CI, también buscan secretos en el código.
Si lo que se filtró fue el token de un bot, el camino es parecido, con algunos detalles propios: mira qué hacer cuando se filtra el token del bot.
Cómo hacerlo en Square Cloud#
En Square Cloud, el paso 2 de la primera sección (actualizar donde se usa la clave) no pasa por el repositorio. Cada aplicación tiene sus propias variables de entorno, que defines en el panel, con la API, con la extensión de VS Code o con la CLI, usando el comando app env set y después app restart. El cambio se aplica en el siguiente reinicio, sin rebuild, y una aplicación no puede leer las variables de otra, aunque estén en la misma cuenta.
Para que el hábito 1 se vuelva regla, el panel importa tu .env local y exporta las variables en formato KEY=VALUE, así que el archivo llega a la aplicación sin entrar nunca en un commit. Si el deploy sale de GitHub, la GitHub Action oficial solo necesita una API key de la plataforma guardada como secret del repositorio, en la entrada token; en otra CI, la CLI lee la misma clave de la variable SQUARECLOUD_API_KEY, sin login. En ambos casos, ninguna credencial queda en el código.
Después de cambiar la clave, sigue los logs en tiempo real de la aplicación para confirmar que volvió a funcionar con el valor nuevo. Mira cómo funcionan las variables de entorno y la GitHub Action.
Infraestructura
Mitigación de DDoS L3/L4/L7 y WAF en todos los planes
Preguntas frecuentes
¿Borrar el archivo o el commit resuelve la filtración?
No. El secreto sigue en el historial de Git, en forks y en clones, y hay programas automáticos que recorren los repositorios públicos buscando claves. La única corrección segura es revocar la clave y crear otra.
¿Tengo que reescribir el historial después de revocar la clave?
En la mayoría de los casos no. Con la clave revocada, el valor antiguo ya no da acceso a nada, y la documentación de GitHub dice que revocar o cambiar la credencial puede ser suficiente. Reescribe el historial si el repositorio tiene otros datos sensibles, como datos personales.
¿GitHub avisa cuando subo una clave?
En los repositorios públicos, el secret scanning se ejecuta automáticamente y, para las claves de proveedores socios, GitHub avisa al proveedor, que puede revocarlas. La protección en el push para cuentas de usuario viene activada por defecto y bloquea el envío de secretos conocidos a repositorios públicos, pero no reconoce todos los tipos de clave.
¿Un repositorio privado también es un riesgo?
Está menos expuesto, pero sigue siendo un riesgo: cualquier persona con acceso al repositorio ve la clave, y un repositorio privado puede volverse público por error. Lo más seguro es no guardar nunca secretos en el código.
Más en Seguridad
Ver los 10 artículos- ¿Qué es un ataque de fuerza bruta y cómo protegerte?Un ataque de fuerza bruta prueba contraseñas en masa hasta acertar una. Mira los tipos (spraying, credential stuffing), cómo funcionan y las defensas con código.
- Hackearon mi aplicación: qué hacer ahoraSi hackearon tu aplicación, contén el acceso, cambia todos los secretos y conserva los logs antes de limpiar. El orden correcto, cómo hallar la causa y cómo volver.
- Checklist de seguridad para publicar un bot, sitio o APIChecklist de seguridad antes de publicar un bot, sitio o API: secretos en variables de entorno, dependencias, HTTPS, cabeceras, permisos mínimos y logs.
- Cómo proteger tu web contra DDoSPara protegerte de un DDoS, combina mitigación en el borde (CDN y WAF) con límite de peticiones, timeouts y caché en la aplicación. Guía paso a paso con código.