# Cómo administrar secretos en pipelines y aplicaciones

**Categoría:** DevOps y cloud · **Nivel:** Intermedio · **Lectura:** 11 min
**Publicada:** 2026-07-28 · **Actualizada:** 2026-07-28 · **Autoría:** Underc0de
**Versión HTML (canónica):** https://underc0de.org/guias/devops-cloud/como-administrar-secretos-en-pipelines-y-aplicaciones/

## Respuesta rápida

Un **secreto** es cualquier credencial que da acceso a algo: una contraseña de base de datos, la clave de una API, un token, un certificado. La regla número uno, sin excepciones: **los secretos nunca se escriben en el código**. El código se versiona en [Git](../../programacion/git-y-github-desde-cero/index.md) y se comparte, y un secreto escrito ahí queda expuesto —y una vez subido, aunque lo borres, sigue en el historial—. En lugar de eso, los secretos se **inyectan en tiempo de ejecución** mediante **variables de entorno**, que el programa lee del sistema al arrancar. A escala, se usa un **gestor de secretos**: un servicio dedicado que los guarda cifrados, controla quién puede leer cada uno, registra los accesos y permite cambiarlos sin tocar el código. Dos prácticas más los completan: la **rotación** (cambiarlos cada cierto tiempo, para que uno filtrado tenga ventana corta) y el **mínimo privilegio** (cada secreto da el menor acceso posible). Y si un secreto se filtra, el orden es claro: **revocarlo de inmediato**, generar uno nuevo, y recién después limpiar el historial —porque mientras siga siendo válido, borrarlo del repositorio no sirve de nada—.

## Por qué no van en el código

La tentación es enorme: la aplicación necesita la contraseña de la base de datos, así que la escribo ahí, en una variable, y listo. Ese atajo es el origen de una parte enorme de las brechas de seguridad, y por una razón que hay que entender del todo.

> **El código se comparte y el historial no olvida**
>
> El código se versiona en [Git](../../programacion/git-y-github-desde-cero/index.md) y se comparte: con el equipo, a veces en un repositorio público, con cualquiera que obtenga una copia. Un secreto escrito en el código queda expuesto a todos ellos. Y hay algo peor: aunque lo borres en un commit posterior, **sigue en el historial** del repositorio, accesible para siempre a quien mire las versiones anteriores. Por eso «lo saco después» no funciona: una vez subido, un secreto se considera comprometido.

Los buscadores automáticos que rastrean repositorios públicos encuentran claves subidas por error en **minutos**, y las explotan. La regla, entonces, no es una formalidad: separar los secretos del código es una de las medidas de seguridad más básicas y de mayor impacto.

## Variables de entorno

La forma básica de sacar los secretos del código son las **variables de entorno**: valores que el programa lee del *sistema* al arrancar, no de su propio código. El código dice «leé la contraseña de la variable `DB_PASSWORD`»; el valor real vive fuera, en el entorno donde corre la aplicación.

```javascript
// MAL: el secreto escrito en el código
const clave = "sk_live_9a8b7c6d5e";   // queda en el historial para siempre

// BIEN: el código lee el valor del entorno
const clave = process.env.API_KEY;    // el valor vive fuera del código
```

La ventaja adicional es que la **misma** aplicación corre en desarrollo, pruebas y producción con credenciales distintas, sin cambiar una línea: solo cambia el entorno. Este principio —la configuración y los secretos viven en el entorno, no en el código— es una de las bases del enfoque moderno de despliegue, y aplica igual en un [pipeline](../como-crear-pipelines-ci-cd-con-github-actions/index.md), un [contenedor](../docker-desde-cero-imagenes-contenedores-y-volumenes/index.md) o la [infraestructura como código](../infrastructure-as-code-con-terraform/index.md).

## El gestor de secretos

Las variables de entorno sacan el secreto del código, pero el valor todavía hay que guardarlo y entregarlo desde algún lado. A escala, ese «algún lado» es un **gestor de secretos**: un servicio dedicado, pensado específicamente para custodiar credenciales. Sus funciones:

- **Almacenamiento cifrado.** Los secretos se guardan cifrados, no en texto plano.
- **Control de acceso.** Se define quién —qué persona, qué servicio— puede leer cada secreto, aplicando el **mínimo privilegio**.
- **Auditoría.** Cada acceso queda registrado, de modo que se puede saber quién leyó qué y cuándo.
- **Cambio centralizado.** Un secreto se cambia en un solo lugar y todas las aplicaciones que lo usan reciben el nuevo, sin tocar código.

Existen gestores de secretos como servicio en las nubes y también soluciones autoalojadas. La pieza clave no es cuál, sino el *patrón*: el secreto vive en el gestor, y las aplicaciones y [pipelines](../como-crear-pipelines-ci-cd-con-github-actions/index.md) lo piden en el momento de arrancar, con permisos acotados.

## Rotación y filtraciones

Dos prácticas completan la gestión de secretos, y la segunda es un plan de emergencia que conviene tener claro *antes* de necesitarlo.

La **rotación** es cambiar los secretos cada cierto tiempo de forma periódica. La lógica: si un secreto se filtró sin que nadie lo note, rotarlo hace que su ventana de utilidad para un atacante sea corta. Un gestor de secretos facilita esto al centralizar el cambio. El [estándar de gestión de claves del NIST](https://csrc.nist.gov/pubs/sp/800/57/pt1/r5/final) trata este ciclo de vida en detalle.

> **Atención**
>
> El orden importa y es contraintuitivo. **Primero** revocás el secreto comprometido, para que deje de ser válido. **Segundo**, generás y desplegás uno nuevo. **Recién entonces** limpiás el historial del repositorio. La razón: mientras el secreto filtrado siga siendo válido, borrarlo del código *no sirve de nada* —el atacante ya lo tiene copiado—. Lo único que corta el riesgo es invalidarlo. Una filtración de credenciales es uno de los fallos que recoge el [OWASP Top 10](../../hacking/owasp-top-10-2025-explicado/index.md), y conviene tratarla con la disciplina de un incidente de seguridad.

## Errores frecuentes

- **Escribir secretos en el código.** Quedan en el historial para siempre; es el error raíz.
- **Subir el archivo de configuración con secretos.** Los archivos de entorno con valores reales no se versionan; se ignoran explícitamente.
- **Creer que borrar un commit basta.** Si el secreto sigue siendo válido, hay que revocarlo, no solo borrarlo.
- **No rotar nunca.** Un secreto eterno filtrado da acceso indefinido.
- **Un secreto con permisos de todo.** El mínimo privilegio acota el daño de una filtración.
- **Compartir secretos por chat o correo.** Quedan en historiales fuera de control; van por el gestor.
- **Registrar secretos en los logs.** Imprimir una variable con la clave la filtra a los registros.

## Preguntas frecuentes

**¿Por qué no puedo escribir las contraseñas en el código?**
Porque el código se versiona en un control de versiones y se comparte —con el equipo, a veces en repositorios públicos, y con cualquiera que obtenga una copia—, de modo que cualquier contraseña, clave o token escrito en él queda expuesto a todas esas personas. Y hay un agravante decisivo: aunque borres el secreto en un commit posterior, sigue quedando registrado en el historial del repositorio, accesible de forma permanente para quien revise las versiones anteriores. Por eso la excusa de «lo saco después» no funciona: en el momento en que un secreto se sube, se considera comprometido. A esto se suma que existen sistemas automáticos que rastrean continuamente los repositorios públicos en busca de credenciales subidas por error y las explotan en cuestión de minutos. Separar los secretos del código no es entonces una formalidad ni una molestia burocrática, sino una de las medidas de seguridad más básicas y de mayor impacto que existen, y su ausencia está detrás de una enorme cantidad de brechas.

**¿Qué son las variables de entorno y cómo ayudan?**
Las variables de entorno son valores que un programa lee del sistema donde se ejecuta, en lugar de tenerlos escritos en su propio código. Aplicadas a los secretos, permiten que el código diga algo como «leé la contraseña de la variable correspondiente» mientras el valor real vive fuera, en el entorno de la máquina o del servicio donde corre la aplicación, y nunca queda escrito en el código ni en el repositorio. Esto aporta dos beneficios importantes. El primero y principal es de seguridad: el secreto se saca del código, que es justamente el lugar donde no debe estar. El segundo es de flexibilidad: la misma aplicación, sin cambiar una sola línea, puede correr en desarrollo, en pruebas y en producción con credenciales distintas, porque lo único que cambia es el entorno que provee cada valor. Este principio de mantener la configuración y los secretos en el entorno y no en el código es una de las bases del enfoque moderno de despliegue de aplicaciones.

**¿Qué es un gestor de secretos?**
Es un servicio dedicado específicamente a custodiar credenciales, que resuelve el problema de dónde guardar y cómo entregar los secretos de forma segura a escala. Cumple varias funciones clave. Almacena los secretos cifrados en lugar de en texto plano. Controla mediante permisos quién puede leer cada secreto, ya sea una persona o un servicio, permitiendo aplicar el principio de mínimo privilegio. Registra cada acceso, de modo que queda una auditoría de quién leyó qué y cuándo. Y centraliza el cambio, de manera que un secreto se actualiza en un solo lugar y todas las aplicaciones que lo usan reciben el nuevo valor sin necesidad de tocar código. Existen gestores de secretos ofrecidos como servicio por las plataformas de nube y también soluciones que se pueden autoalojar. Lo importante no es cuál se elija, sino adoptar el patrón: el secreto vive en el gestor, y las aplicaciones y los pipelines lo solicitan en el momento de arrancar, con permisos acotados y de forma auditable.

**¿Por qué hay que rotar los secretos?**
Rotar un secreto significa cambiarlo por uno nuevo cada cierto tiempo de forma periódica, y la razón es acotar el daño de una filtración que podría no haberse detectado. Si un secreto permaneciera inalterado para siempre y en algún momento se filtrara sin que nadie lo advirtiera, un atacante tendría acceso indefinido con esa credencial. Al rotarlo periódicamente, en cambio, cualquier secreto comprometido deja de ser válido en la siguiente rotación, de modo que su ventana de utilidad para quien lo haya obtenido es corta. La rotación es una defensa en profundidad: no evita la filtración, pero limita cuánto tiempo sirve. Un gestor de secretos facilita mucho esta práctica, porque permite cambiar el valor en un único lugar y propagarlo automáticamente a todo lo que lo use, sin la fricción de actualizarlo a mano en muchos sitios, que es justamente lo que suele llevar a que la rotación no se haga. Los estándares de gestión de claves tratan este ciclo de vida en detalle.

**¿Qué hago si subí un secreto al repositorio por error?**
Lo primero y más importante es entender el orden correcto de las acciones, que es contraintuitivo. El primer paso debe ser revocar el secreto comprometido de inmediato, es decir invalidarlo en el servicio al que da acceso para que deje de funcionar. El segundo paso es generar un secreto nuevo y desplegarlo donde haga falta para que la aplicación siga operando. Y solo el tercer paso es limpiar el historial del repositorio para quitar el secreto de las versiones anteriores. La razón de este orden es crucial: mientras el secreto filtrado siga siendo válido, borrarlo del repositorio no sirve absolutamente de nada, porque quien lo haya visto ya tiene una copia y puede usarlo; lo único que corta el riesgo real es invalidar la credencial. Por eso tratar una filtración de secretos debe encararse como lo que es, un incidente de seguridad, aplicando los principios de la respuesta ante incidentes y de la gestión de vulnerabilidades: contener primero, remediar después.

**¿Esta regla aplica también a Docker, Kubernetes y los pipelines?**
Sí, es exactamente la misma regla en todos esos contextos, porque el principio de fondo es siempre el mismo: los secretos no deben quedar incrustados en nada que se versione, se comparta o se distribuya. En Docker, eso significa no escribir secretos en la imagen ni en el Dockerfile, ya que quedan grabados en las capas, e inyectarlos como variables de entorno al ejecutar. En Kubernetes, significa no ponerlos en los manifiestos versionados sino usar los objetos de secretos y un gestor externo. En los pipelines de integración y despliegue continuos, significa no escribirlos en el archivo del workflow sino cargarlos en el almacén de secretos cifrados de la plataforma. En la infraestructura como código con Terraform, significa no ponerlos en los archivos de configuración y además proteger el estado, que puede contenerlos. En todos los casos el patrón es idéntico: el secreto vive en un mecanismo aparte pensado para protegerlo, se inyecta o se referencia en tiempo de ejecución, y jamás se incrusta en el código, la imagen, el manifiesto o la configuración que se guarda y se comparte.

## Fuentes

Documentación oficial y material de la comunidad consultados para esta guía. Fecha de consulta: 28 de julio de 2026.

### Aportes de la comunidad Underc0de

1. **Underc0de, foro.** [Sección Hacking](https://underc0de.org/foro/hacking/). Filtración de credenciales y su impacto en seguridad.
2. **Underc0de, foro.** [Sección Programación](https://underc0de.org/foro/programacion/). Manejo de configuración y credenciales en el código.

### Documentación oficial

1. **OWASP.** [Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html). Prácticas de referencia, citadas en la guía.
2. **NIST.** [SP 800-57: Recommendation for Key Management](https://csrc.nist.gov/pubs/sp/800/57/pt1/r5/final). Ciclo de vida y rotación de claves.
3. **OWASP.** [OWASP Top 10](https://owasp.org/www-project-top-ten/). Los fallos de configuración y de identidad más habituales.
4. **The Twelve-Factor App.** [Config](https://12factor.net/config). Por qué la configuración y los secretos van en el entorno.

## Guías relacionadas

- [Pipelines CI/CD](../como-crear-pipelines-ci-cd-con-github-actions/index.md)
- [IaC con Terraform](../infrastructure-as-code-con-terraform/index.md)
- [Passkeys y Zero Trust](../../hacking/passkeys-autenticacion-sin-contrasena-y-zero-trust/index.md)
- [Git y GitHub desde cero](../../programacion/git-y-github-desde-cero/index.md)
- [Índice de DevOps y cloud](../index.md)
