Objetivos de aprendizaje
Después de leer este artículo podrás:
- Mover los secretos escritos en el código a variables de entorno
- Impedir que los secretos lleguen a Git con .gitignore, un escaneo pre-commit y push protection
- Reaccionar bien cuando un secreto ya llegó a un commit
En esta página
- ¿Por qué un secreto escrito en el código es un problema?
- ¿Cómo saco un secreto del código?
- ¿Cómo evito que los secretos lleguen a Git?
- ¿Dónde deberían vivir los secretos?
- ¿Puedo guardar secretos en el código del front-end?
- ¿Qué hago si un secreto ya llegó a un commit?
- ¿Cómo compruebo que funcionó?
- Cómo hacerlo en Square Cloud
- Preguntas frecuentes
Un secreto es cualquier valor que da acceso: un token de bot, una contraseña de base de datos, una clave de API de pagos, una clave de firma. En cuanto uno llega a un commit de Git, pierdes el control sobre él. Se copia a cada clon, aparece en los diffs y, si el push es público, los bots pueden encontrarlo en poco tiempo.
La solución es más un hábito que una herramienta: el código pide el secreto en tiempo de ejecución, y el secreto vive en otro lugar. Los pasos de abajo van desde la primera refactorización hasta qué hacer cuando algo se filtra.
¿Por qué un secreto escrito en el código es un problema?#
Git nunca olvida. Borrar una línea en un commit posterior deja el valor antiguo en el historial, y el historial se copia a cada clon y fork. Los repositorios privados tampoco son un lugar seguro: con el tiempo más personas reciben acceso de lectura, los sistemas de CI imprimen logs y los repositorios se hacen públicos por accidente.
Escribir el secreto en el código también acopla el código y el entorno. El mismo archivo no puede ejecutarse con una clave de prueba en tu computadora y una clave real en producción sin editar el código fuente.
¿Cómo saco un secreto del código?#
Léelo de una variable de entorno. Antes:
const token = "MTIzNDU2Nzg5MA.fake.token"; // fijo en el código: nunca hagas estoDespués, en Node.js, con una comprobación que falla rápido si falta el valor:
// index.js
const token = process.env.DISCORD_TOKEN;
if (!token) {
throw new Error("DISCORD_TOKEN no está definido");
}Lo mismo en Python:
import os
token = os.environ["DISCORD_TOKEN"] # lanza KeyError si faltaPara desarrollo local, pon los valores en un archivo .env y cárgalo. Node.js puede hacerlo de forma nativa con una opción (--env-file, disponible desde la v20.6.0 y ya no experimental en la v22.21 y la v24.10):
node --env-file=.env index.jsSi el archivo puede no existir, usa --env-file-if-exists=.env (desde la v22.9.0). Sin ella, Node.js lanza un error cuando falta el archivo. Una variable ya definida en el entorno real gana sobre el archivo. Mira el archivo .env para la sintaxis y la carga en Python, y variables de entorno para el concepto.
¿Cómo evito que los secretos lleguen a Git?#
Usa tres capas, porque cada una atrapa lo que las otras dejan pasar.
1. Ignora el archivo. Añade esto al .gitignore antes de crear el primer .env:
.env
.env.*
!.env.exampleDespués sube un .env.example con los nombres de las variables y valores falsos, para que tu equipo sepa qué definir:
DISCORD_TOKEN=replace_me
DATABASE_URL=postgresql://user:password@localhost:5432/mydbEl .gitignore solo afecta a los archivos que Git todavía no rastrea. Si .env ya estaba en un commit, ejecuta primero git rm --cached .env.
2. Escanea antes de hacer commit. Gitleaks es un escáner de código abierto. Como hook de pre-commit, añade esto a .pre-commit-config.yaml (cambia el rev por la versión actual, que aparece en la página de releases del proyecto, o ejecuta pre-commit autoupdate) y después ejecuta pre-commit install:
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1
hooks:
- id: gitleaksPara escanear una vez todo el historial de un repositorio existente:
gitleaks git -v .Los comandos antiguos detect y protect quedaron obsoletos en la v8.19.0, sustituidos por git, dir y stdin.
3. Bloquea en el servidor. La push protection de GitHub rechaza los pushes que contienen patrones de secretos reconocidos. Para los usuarios, viene activada por defecto en los repositorios públicos de GitHub.com. Activarla en un repositorio depende de un administrador del repositorio o del propietario de la organización y requiere GitHub Secret Protection. Es una red de seguridad, no un sustituto de las dos primeras capas, porque solo reconoce los patrones admitidos y los personalizados.
¿Dónde deberían vivir los secretos?#
Elige el lugar más simple que sirva para cada etapa:
| Etapa | Dónde vive el secreto |
|---|---|
| Desarrollo local | Un archivo .env ignorado, o tu shell |
| CI/CD | Los secretos cifrados del proveedor de CI, pasados al job como variables de entorno |
| Producción | La configuración de variables de entorno de la plataforma de hosting, o un gestor de secretos dedicado |
Un gestor de secretos dedicado añade control de acceso, logs de auditoría y rotación. Vale la pena cuando muchas personas o servicios comparten credenciales. Para un solo bot o API, las variables de entorno de la plataforma suelen bastar.
Hay dos reglas que valen en todas partes. Da a cada entorno su propio secreto, para que una clave de desarrollo filtrada no pueda tocar producción. Y da a cada secreto el menor permiso que necesite, como un usuario de base de datos de solo lectura para un script de reportes.
¿Puedo guardar secretos en el código del front-end?#
No. Todo lo que se envía al navegador es público. Next.js, por ejemplo, incrusta en el bundle de JavaScript, en el momento del build y a propósito, las variables con el prefijo NEXT_PUBLIC_. Otros frameworks tienen prefijos parecidos. Una clave secreta de pagos o una URL de base de datos en una variable del front-end queda publicada para cada visitante.
Mantén los secretos reales en un servidor y haz que el navegador llame a tu propio endpoint. Los identificadores públicos, como una clave publicable pensada para el cliente, están bien en el código del front-end.
¿Qué hago si un secreto ya llegó a un commit?#
El orden importa. Primero revoca, después limpia.
- Revoca o rota el secreto ya. Genera un token o una contraseña nueva en el proveedor y actualiza tu deploy. La propia guía de GitHub pone esto primero: una vez revocado el valor antiguo, ya no se puede usar, lo que puede resolver el problema por sí solo.
- Busca usos indebidos. Revisa los logs de auditoría o de uso del proveedor en busca de actividad que no reconozcas.
- Quítalo del historial, si quieres. Usa git filter-repo para reescribir el historial y después haz un force-push. Pide a los colaboradores que vuelvan a clonar, o pueden subir otra vez los datos antiguos.
- Acepta los límites. Reescribir no limpia otros clones, forks ni vistas en caché de commits antiguos. Por eso el paso 1 es la solución real.
Para los pasos exactos después de una filtración en GitHub, lee qué hacer cuando una clave de API queda expuesta en GitHub. Una lista más amplia de comprobaciones de deploy está en la lista de seguridad para el deploy.
¿Cómo compruebo que funcionó?#
git ls-files | grep -i "\.env"lista los archivos env rastreados. Solo debería aparecer.env.example.git log -p -S"prefijo-de-tu-secreto"busca en el historial un valor que te preocupa. Usa un prefijo, no el secreto entero.- Ejecuta
gitleaks git -v .y confirma que no reporta filtraciones. - Arranca la app sin la variable definida. Debería fallar con tu mensaje de error claro, no ejecutarse con un valor por defecto.
Cómo hacerlo en Square Cloud#
En Square Cloud, defines las variables de entorno por aplicación: en el panel, con la API, en la CLI o en la extensión de VS Code. El panel puede importar un archivo .env y exportar las variables de vuelta como KEY=VALUE, así es fácil mantener sincronizados tu archivo local y producción.
Un cambio se aplica en el siguiente reinicio, sin rebuild. Tu código lee los valores de la forma habitual, con process.env u os.environ, así que nada en tu código fuente tiene que saber dónde se guardan. Cada aplicación también recibe su propia variable SQUARECLOUD_APP_ID en tiempo de ejecución.
Como las variables se definen por aplicación, puedes dar a cada app sus propios tokens y dejar el archivo .env fuera del ZIP o del repositorio que despliegas. Lee más en la página de variables de entorno.
Infraestructura
Mitigación de DDoS L3/L4/L7 y WAF en todos los planes
Preguntas frecuentes
¿Es seguro subir un secreto a un repositorio privado?
No se recomienda. Cualquiera con acceso de lectura, cada clon, cada log de CI y cada futuro colaborador puede verlo, y un repositorio puede volverse público por error. Trata el repositorio como un lugar solo para código.
¿Borrar el secreto en un commit nuevo soluciona la filtración?
No. El secreto sigue en el historial de Git y en cada clon y fork. La única solución real es revocar el secreto y emitir uno nuevo. Reescribir el historial es un paso de limpieza posterior.
¿Un archivo .env es un gestor de secretos?
No. Un archivo .env es texto plano en el disco, útil para desarrollo local. En producción, define las variables en tu plataforma de hosting o en un gestor de secretos dedicado, y deja el archivo fuera de Git.
¿Puedo poner secretos en el código del front-end?
No. Todo lo que se envía al navegador lo puede leer cualquier visitante. Las variables con prefijos como NEXT_PUBLIC_ se incrustan a propósito en el bundle de JavaScript. Mantén los secretos reales en un servidor y expón solo un endpoint.
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.