«Oigo una y otra vez que la seguridad importa, pero ¿por dónde empiezo siquiera?» Este es el primerísimo paso para desarrolladores indie. No para asustarte — solo cosas sobre las que puedes actuar hoy, en orden.
Por qué empezar por los secretos (.env y claves de API)
La mayoría de los incidentes reales empiezan no con ataques sofisticados sino con un secreto filtrado. Los dos casos sobre los que se construye este sitio fueron ambos fugas de secretos:
Protege tus secretos y previenes la mayoría de los incidentes comunes. Por eso empezamos aquí.
Qué es .env (en 30 segundos)
.env es un archivo que reúne los valores secretos de tu app: la contraseña de la base de datos, las claves de API externas, la clave que cifra las sesiones. Como los secretos están juntos en un solo archivo, una fuga los expone todos a la vez — así que es el archivo que proteger primero (→ Glosario: qué es .env).
Dónde pueden vivir los secretos (.env, variables de entorno, gestores de secretos)
.env no es el único sitio para los secretos. Elige según la escala y el uso.
| Dónde | Ideal para | Cuidado con |
|---|---|---|
Un archivo .env | Desarrollo local, un único servidor pequeño | Mantenlo fuera de Git y fuera de los directorios públicos |
| Los ajustes de variables de entorno del hosting (introducidos en un panel) | Producción | Limita quién accede al panel; mantén los valores fuera de los registros de compilación |
| Los secretos de la CI (pruebas y despliegue automáticos) | Automatización como GitHub Actions | Las herramientas externas que se ejecutan en la CI pueden ver los valores; pasa claves solo con los permisos necesarios |
| Un gestor de secretos | Varias personas o varios servidores | Mantén el acceso de lectura al mínimo y rota con regularidad |
Para los secretos de la CI, el incidente de Codecov de 2021 es una referencia útil. Se manipuló una herramienta externa que se ejecutaba en la CI y se robaron los secretos guardados en las variables de entorno de la CI (→ el incidente de Codecov).
Claves que puedes publicar y claves que no
Algunas claves de API están pensadas para ir dentro de navegadores o apps móviles; otras son solo para servidores. Da por hecho que cualquier cosa enviada a un navegador la puede leer cualquiera.
| Ejemplo | ¿Se puede publicar? | Por qué |
|---|---|---|
Clave publicable de Stripe (empieza por pk_) | Sí | La documentación dice que se puede incluir en el código del front-end; no puede hacer operaciones sensibles como crear cobros |
Clave secreta (sk_) o restringida (rk_) de Stripe | No | Permiten operaciones del lado del servidor; la documentación recomienda claves restringidas con permisos acotados |
Variable de entorno de Next.js con NEXT_PUBLIC_ | Publicada | Su valor se incrusta en el JavaScript del navegador al compilar |
Variable de entorno de Next.js sin NEXT_PUBLIC_ | No publicada (solo servidor) | Pon aquí los valores secretos |
Si dudas, consulta en la documentación oficial del servicio si la clave se puede usar en el lado del cliente. Si no lo dice, trátala como una clave que no debes publicar.
Qué significa la fuga de una clave de API
Una clave de API es «una cadena que permite a un servicio tratar a quien la usa como si fueras tú». En las manos equivocadas, el daño se extiende así.
Las claves robadas a menudo se revenden y se abusan con retraso — «al principio no pasa nada, luego una factura sorpresa» es el patrón clásico. Así que «después de que lo notes» es demasiado tarde; el punto es no filtrarlas en primer lugar.
Qué hacer si una clave puede haberse filtrado
Borrar la clave de tu código no la detiene. El informe de 2025 de GitGuardian constató que el 70 % de los secretos filtrados en repositorios públicos en 2022 seguían siendo válidos en el momento del informe. Responde en este orden.
- Revoca o rota la clave en el panel del emisor. Si el servicio ofrece un periodo de gracia, termina la clave filtrada «ahora»
- Configura la clave nueva en producción y confirma que la app funciona
- Revisa el historial de uso y la facturación del emisor por si hay actividad que no fue tuya
- Quitarla de los archivos y del historial de Git puede esperar a después de la revocación (borrar sin más no detiene a quien ya tiene una copia)
Los detalles están en 540,000 credentials published on GitHub are still valid (en inglés). GitHub activa por defecto la «push protection», que impide a una cuenta personal hacer push de secretos a un repositorio público, pero no detecta todos los tipos de secretos.
Cuatro hábitos para empezar hoy
Nada difícil. Solo estos cuatro.
No la expongas
Nunca pongas .env ni el cuerpo de la app en un directorio visible en la web (la raíz web). Expón solo public/. Pasos concretos para hosting compartido: esta guía.
No le hagas commit
Añade .env* a .gitignore (permite !.env.example); comparte solo un ejemplo sin valores. Una vez con commit es recuperable del historial, así que mantenlo fuera desde el inicio.
Rota todo si se filtra
No solo una clave — rota cada secreto que pudiera haberse filtrado. Orden: API externa / OAuth → claves de cifrado → correo → BD. Actúa como si las hubieran visto.
Autocomprueba
De vez en cuando confirma que /.env no se puede abrir desde fuera (abajo).
Autocomprobación (solo contra dominios que posees)
# Un 200 con cuerpo significa que está expuesto. 403/404 está bien por ahora.
curl -sI https://tu-dominio/.env | head -1
curl -sI https://tu-dominio/.git/config | head -1Comprobar esto en cada despliegue detecta a tiempo los errores de ubicación.
Además de lo que se ve desde fuera, revisa también Git y el resultado de la compilación (ejecútalo en tu propio repositorio).
# ¿Se hizo commit de .env alguna vez? (cualquier salida significa que sí, en algún momento)
git log --all --oneline -- .env
# archivos tipo env que Git sigue ahora (todo lo que no sea .env.example merece un vistazo)
git ls-files | grep -i "env"Para confirmar que ninguna clave llega al navegador, busca los primeros caracteres de la clave en la carpeta de salida de la compilación (en Next.js, .next/static). También puedes pegar el código en el escáner de fugas de secretos antes de publicar (no se envía nada a ningún sitio).
Errores comunes vs el primer paso correcto
Común
- «Funciona», así que dejas
.envjusto bajo public - «Lo borro luego», así que haces commit de
.envuna vez - Rotar solo la única clave de la que viste abuso
El primer paso correcto
- Cuerpo de la app fuera de la raíz web, exponer solo
public/ - Excluir
.envvía.gitignoredesde el inicio - Si se filtra, rotar cada secreto del entorno
Siguientes pasos
A partir de aquí, los siguientes temas son «los valores por defecto arriesgados de tu stack» y «un sistema para no quedarse atrás con los CVE publicados». Sin prisa, uno a uno.
Fuentes
- Next.js, "How to use environment variables in Next.js" (16.x) — nextjs.org
- Stripe Docs, "API keys" — docs.stripe.com
- Laravel 13.x, "Configuration" (Environment File Security) — laravel.com
- GitHub Docs, "About push protection" — docs.github.com
- GitGuardian, "The State of Secrets Sprawl 2025" — blog.gitguardian.com
Leer a continuación
-
Tras una fuga: 543,699 credentials exposed on GitHub are still valid — why you must revoke, not just delete (en inglés)
-
La filtración de Gyazo (septiembre de 2026): qué se filtró y qué deben hacer hoy los usuarios (en inglés)
-
Glosario: qué es .env · qué es un CVE · qué es un RCE
-
Defensa: mantén .env fuera de la web pública · higiene de CVE en Next.js
-
Incidente: una clave de API robada facturada de forma fraudulenta
-
Incidente: una clave robada hizo que banearan la cuenta
-
Cadena de suministro: cuando un solo npm install roba tus credenciales (en inglés; código ajeno ejecutándose en el entorno donde guardas tus claves)