Cómo gestionar de forma segura claves API y secretos en el código
Haces commit de tu código, lo subes a GitHub y sigues adelante. Días después descubres que tu clave API fue extraída de un repositorio público y utilizada para acumular miles de dólares en facturas de la nube. Este no es un caso aislado; es uno de los errores de seguridad más comunes y costosos en el desarrollo moderno. Los secretos codificados directamente en el código fuente son un regalo para los atacantes, y son sorprendentemente fáciles de evitar.
Por qué los secretos codificados son tan peligrosos
Cuando incrustas una clave API, una contraseña de base de datos o un token privado directamente en tu código, pierdes el control sobre quién puede verlo. El código fuente viaja: se clona, se bifurca, se copia en imágenes de Docker, se pega en aplicaciones de chat y, a veces, se publica accidentalmente. Una vez que un secreto está en el control de versiones, vive para siempre en el historial de Git, incluso si lo eliminas en un commit posterior.
Los atacantes escanean activamente repositorios públicos en busca de patrones que parezcan claves. Los bots automatizados pueden encontrar y explotar una clave filtrada en cuestión de minutos. Incluso en repositorios privados, los secretos codificados violan el principio de mínimo privilegio: cada desarrollador con acceso de lectura obtiene automáticamente credenciales de producción.
Regla n.º 1: Nunca codifiques secretos
Esto suena obvio, pero es la base. El primer paso es eliminar cualquier secreto de tus archivos fuente. Esto incluye no solo cadenas obvias como sk_live_... sino también cadenas de conexión, claves privadas y secretos de firma de webhooks.
En su lugar, tu código debe leer los secretos del entorno en tiempo de ejecución. Aquí tienes un ejemplo simple en Python:
import os
api_key = os.environ.get("PAYMENT_API_KEY")
if not api_key:
raise RuntimeError("PAYMENT_API_KEY is not set")
En Node.js, usarías process.env.PAYMENT_API_KEY. En Go, os.Getenv("PAYMENT_API_KEY"). El patrón es universal: el código espera que el secreto se proporcione externamente.
Usar variables de entorno de forma segura
Las variables de entorno son una gran mejora, pero no son una bala de plata. Pueden filtrarse a través de informes de errores, registros de depuración o listados de procesos. Sigue estas prácticas:
- Nunca registres variables de entorno. Evita volcar
process.envoos.environen manejadores de errores. - Usa un archivo
.envsolo para desarrollo local. Agrega.enva.gitignoredesde el primer día. - Proporciona un archivo
.env.examplecon valores de marcador de posición para que los nuevos desarrolladores sepan qué configurar. - Valida los secretos requeridos al inicio. Falla rápido si falta una clave, en lugar de fallar más tarde en producción.
Para el desarrollo local, bibliotecas como python-dotenv o dotenv para Node.js facilitan la carga de un archivo .env sin codificar nada. Solo recuerda: ese archivo nunca debe ser confirmado.
Gestores de secretos centralizados para producción
Las variables de entorno funcionan bien para proyectos pequeños, pero se vuelven difíciles de manejar cuando tienes muchos servicios, múltiples entornos y necesidad de auditoría. Un gestor de secretos dedicado resuelve estos problemas almacenando secretos cifrados en reposo, controlando el acceso con políticas detalladas y proporcionando un registro de auditoría.
Opciones populares incluyen:
- HashiCorp Vault – autoalojado, muy flexible, admite secretos dinámicos.
- AWS Secrets Manager – integración nativa con servicios de AWS, rotación automática.
- Google Secret Manager – similar para GCP.
- Azure Key Vault – para entornos de Microsoft Azure.
- Doppler, Infisical o 1Password Secrets Automation – opciones SaaS multiplataforma.
Tu aplicación obtiene secretos del gestor al inicio o bajo demanda, a menudo usando un SDK. Esto desacopla el almacenamiento de secretos del código y te permite rotar credenciales sin volver a desplegar.
Secretos en pipelines CI/CD
Tus pipelines de compilación y despliegue también necesitan secretos, como contraseñas de registro o tokens de despliegue. La mayoría de los sistemas CI (GitHub Actions, GitLab CI, CircleCI) proporcionan almacenamiento cifrado de secretos. Usa esas características en lugar de poner secretos en archivos de configuración del pipeline.
Por ejemplo, en GitHub Actions defines secretos en la configuración del repositorio y los referencias así:
steps:
- name: Deploy
run: ./deploy.sh
env:
API_TOKEN: ${{ secrets.DEPLOY_API_TOKEN }}
Ten cuidado con las solicitudes de extracción de bifurcaciones: los secretos no se pasan a los flujos de trabajo activados por PRs de bifurcación de forma predeterminada, lo cual es bueno. Nunca muestres secretos en los registros; enmascáralos si tu sistema CI lo admite.
Rota los secretos regularmente
Incluso con un almacenamiento perfecto, los secretos pueden filtrarse por otros canales: un portátil comprometido, un servicio de registro mal configurado o un empleado que se va. La rotación limita la ventana de exposición.
Establece un programa de rotación basado en la sensibilidad. Las claves de alto valor (pasarelas de pago, API de administración) podrían rotar cada 30–90 días. Las claves de menor riesgo pueden rotar con menos frecuencia. Automatiza la rotación donde sea posible: AWS Secrets Manager y Vault pueden rotar credenciales de bases de datos automáticamente.
Al rotar, asegúrate de que tu aplicación pueda manejar múltiples secretos válidos durante la transición. Un patrón común es aceptar tanto el secreto antiguo como el nuevo durante un breve período, luego desactivar el antiguo.
Detectar y prevenir filtraciones
Prevenir es mejor que curar, pero la detección es tu red de seguridad. Usa ganchos de pre-commit para escanear secretos antes de que se confirmen. Herramientas como git-secrets, trufflehog o gitleaks pueden detectar confirmaciones accidentales.
También habilita el escaneo de secretos en tu plataforma de alojamiento Git (GitHub, GitLab, Bitbucket ofrecen esto). Si un secreto se filtra, revócalo inmediatamente y rótalo. Eliminar el commit no es suficiente; asume que el secreto está comprometido en el momento en que toca un repositorio remoto.
Comparación de enfoques de almacenamiento de secretos
| Método | Mejor para | Riesgos |
|---|---|---|
| Variables de entorno | Aplicaciones pequeñas, desarrollo local | Filtración a través de registros, inspección de procesos |
Archivos .env |
Desarrollo local | Commit accidental, sin cifrado |
| Gestores de secretos | Producción, equipos | Complejidad, dependencia añadida |
| Almacenes de secretos CI/CD | Pipelines de compilación y despliegue | Limitado al alcance del pipeline |
Preguntas frecuentes
¿Puedo almacenar secretos en un repositorio privado?
No. Los repositorios privados aún tienen muchos usuarios e integraciones con acceso de lectura. Los secretos pueden filtrarse a través de bifurcaciones, registros de CI o una cuenta comprometida. Siempre usa variables de entorno o un gestor de secretos, incluso para código privado.
¿Qué debo hacer si confirmo accidentalmente un secreto?
Revoca y rota el secreto inmediatamente. Simplemente eliminar el commit o reescribir el historial no es suficiente porque el secreto puede ya estar en caché o clonado. Trátalo como comprometido y reemplázalo.
¿Son las variables de entorno lo suficientemente seguras para producción?
Son mejores que codificar directamente, pero no son ideales para producción a gran escala. Las variables de entorno pueden exponerse en volcados de fallos, puntos finales de depuración o listados de procesos. Para producción, usa un gestor de secretos dedicado con controles de acceso y auditoría.
Cuando necesites formatear o validar rápidamente archivos de configuración JSON que contienen ajustes no sensibles, el JSON Formatter puede ayudarte a detectar errores de sintaxis antes de que rompan tu despliegue. Recuerda: nunca pegues secretos reales en herramientas en línea.