Asegurar los runners de CI/CD no es un truco de seguridad, sino una tarea operativa sostenible: los runners obtienen código fuente, generan artefactos y con frecuencia tienen acceso a credenciales, cachés y la red interna. Para administradores y operadores es crucial reducir la superficie de ataque de forma medible y disponer de rutas claras de verificación y reversión. Esta guía proporciona medidas concretas, pasos de comprobación y troubleshooting para el aislamiento de credenciales, una limpieza robusta del workspace y la protección de la cadena de build.
Por qué los runners son un vector de ataque crítico
Los runners son entornos de ejecución para jobs de CI/CD (builds, tests, packaging). Un runner comprometido puede:
- Exfiltrar secretos (tokens, claves SSH, credenciales de cloud).
- Alterar artefactos o firmarlos de forma manipulada.
- Realizar cache-poisoning y así afectar builds posteriores.
- Permitir pivoting hacia la red interna.
Distinción importante: trusted-Builds (p. ej. ramas protegidas o releases) frente a untrusted-Builds (forks, PRs externas, contribuciones públicas). Para los untrusted-Builds debe asumirse operativamente que el job es potencialmente malicioso.
Principios básicos: privilegios mínimos, aislamiento, trazabilidad
Endurezca la operación en torno a tres objetivos medibles:
- Objetivo de aislamiento: Ningún job debe poder ver el estado de otro job.
- Objetivo de credenciales: Los jobs reciben únicamente las credenciales mínimas necesarias, preferiblemente de corta duración.
- Objetivo de integridad: La procedencia y la inmutabilidad de dependencias y artefactos deben ser trazables.
Estos objetivos se pueden operacionalizar, probar y auditar.
Aislamiento de credenciales: implementación, motivos y trampas típicas
Aislamiento de credenciales significa: nada de tokens estáticos de uso general. Segmenten identidades según la fase de la pipeline (build, package, release, deploy) y el contexto. Utilicen tokens efímeros (TTL en minutos/horas) vía OIDC, STS (Security Token Service) o leases de HashiCorp Vault. Las credenciales de corta duración limitan el blast radius en caso de compromiso y facilitan el revocado.
Opciones técnicas y su uso
OIDC (OpenID Connect) es un protocolo para emitir tokens efímeros; conecta sistemas de CI con Cloud-IAM o Vault sin secretos permanentes. KMS/HSM (Key Management Service / Hardware Security Module) almacena claves privadas fuera de los runners normales. Vault ofrece secretos dinámicos (p. ej. credenciales de bases de datos con leases). Cada opción exige requisitos operativos: OIDC precisa claims de token fiables; Vault requiere alta disponibilidad y políticas de acceso adecuadas.
Ejemplo: Vault-Policy para Package-Push
# Vault policy (HCL) - erlaubt Token zum Schreiben in ein internes Artefakt-Repo
path "secret/data/ci/artifacts/*" {
capabilities = ["create", "update", "read"]
}
Por qué funciona: Vault emite tokens con duración limitada, y la policy restringe los paths. Cuándo falla: cuando los runners persisten el token de Vault (p. ej. en caché) o las policies están definidas demasiado amplias.
Firmado limitado por políticas mediante un servicio de firma
Las claves privadas de firma no deben residir en runners normales. Un servicio de firma (un servicio interno que firma mediante KMS/HSM) recibe hashes de artefactos, verifica políticas (p. ej. que el build provenga de una rama protegida) y después realiza la firma. La operación de firma requiere logs de auditoría separados y una autenticación estricta.
Asegurar los runners de CI/CD: aislamiento a nivel de infraestructura
Seleccione el aislamiento en función del riesgo y la rentabilidad:
- Host-Runner: Rápido, pero solo para trabajos plenamente confiables.
- Container-Runner: Buen rendimiento, pero solo con rootless y políticas de montaje estrictas.
- Ephemeral VM/Instance-Runner: Aislamiento máximo; por trabajo una VM nueva o un snapshot. Costes más altos, seguridad máxima.
Los Ephemeral-Runner son especialmente recomendables para builds no confiables: tras finalizar, la instancia se destruye para evitar persistencia.
Ejemplo: Kubernetes-Runner como Job efímero
apiVersion: batch/v1
kind: Job
metadata:
name: runner-job-{{ .RunID }}
spec:
template:
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: builder
image: registry.internal/runner-image:stable
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
RESTartPolicy: Never
backoffLimit: 0
Por qué ayuda: Kubernetes permite Namespaces, NetworkPolicies y contextos de seguridad de Pods para RESTringir. Atención: configuraciones erróneas de RBAC o de volúmenes pueden socavar el aislamiento.
Limpieza segura del workspace: robusta y resistente a manipulaciones
Una limpieza defectuosa permite persistencia. Los problemas surgen por handles abiertos, sistemas de archivos montados, trucos con symlinks y ACLs RESTrictivas. Una limpieza robusta implementa varias capas de protección: workspaces dedicados, normalización de ownership, –one-file-system al borrar y comprobaciones con registro de auditoría.
Linux: Limpieza ampliada incluyendo verificación de handles
#!/usr/bin/env bash
set -euo pipefail
JOB_DIR="$1"
RUNNER_UID=1001
RUNNER_GID=1001
# 1) Prozesse beenden, die in JOB_DIR arbeiten
fuser -k -TERM -m "$JOB_DIR" || true
sleep 1
fuser -k -KILL -m "$JOB_DIR" || true
# 2) Ownership und Rechte normalisieren
chown -R "${RUNNER_UID}:${RUNNER_GID}" "$JOB_DIR" 2>/dev/null || true
chmod -R u+rwX,go-rwx "$JOB_DIR" 2>/dev/null || true
# 3) Prüfen auf Mountpoints im Jobdir
mountpoints=$(findmnt -n -o TARGET --target "$JOB_DIR" || true)
if [ -n "$mountpoints" ]; then
echo "Found mounts: $mountpoints" >&2
# Option: detach mounts safely or warn and abort
fi
# 4) Löschen sicher durchführen
rm -rf --one-file-system "$JOB_DIR"
Por qué fuser es necesario: los handles de archivos abiertos impiden la eliminación; los procesos deben terminarse correctamente. El script puede fallar si un job ha iniciado procesos del sistema que el script no puede terminar—por eso el registro y los niveles de advertencia son importantes.
Windows: Handles, plan de reinicio e interacción con antivirus
En Windows son habituales los locks por servicios y AV. Complemente la limpieza con comprobaciones de handles (Sysinternals Handle/Process Explorer), reintentos y una ruta de reinicio planificada si la eliminación no es posible. Los simples reintentos no siempre bastan ante locks persistentes — documente una ruta de rollback.
Seguridad de la cadena de compilación: orígenes de paquetes, cachés y firma
Proteja la cadena de compilación mediante la separación de orígenes de paquetes, proxies con listas de permitidos, cachés controlados y políticas de artefactos inmutables.
Espejos internos y RESTricción de egress
Además de listas de permitidos para endpoints de paquetes, los runner deberían tener solo egress definido: VCS, mirror, repositorio de artefactos, KMS/servicio de firmado. Las ACLs de egress reducen las posibilidades de exfiltración/conexiones a infraestructura de Command-and-Control. Pruebe los cambios primero en modo monitor (solo registro) antes de bloquear.
Endurecimiento del repositorio de artefactos
Establezca Write-Policies (non-overwrite), políticas de retención y los flags require-signed-artifact cuando su repositorio lo soporte. Los audit-logs deben mostrar quién y cuándo publicó un artefacto. Regla de ejemplo: „Los releases solo pueden publicarse tras la firma por el servicio de firmado“.
Estrategias de caché contra el envenenamiento
Separe las cachés por zonas de confianza y por proyecto. Evite cachés compartidos con permisos de escritura para jobs no confiables. Utilice invalidación por TTL y hashes de caché registrados para detectar el envenenamiento.
Endurecimiento de red y host: medidas concretas
Trate los Runner como componentes de infraestructura crítica:
- segmentos de red dedicados o VLANs
- ACLs de egress definidas
- firewall del host y proceso de parcheo
- monitorización y registros centralizados
Ejemplo: regla iptables simple para egress (VM-Runner)
# Erlaube nur DNS, HTTP(S) zu mirror.example und signing.example
iptables -A OUTPUT -m owner --uid-owner runner -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -p tcp -d mirror.example --dport 443 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -p tcp -d signing.example --dport 443 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -j DROP
Por qué ayuda: incluso si un job intenta establecer comunicación maliciosa, el egress queda limitado. Atención: DNS-over-HTTPS y otros caminos de evasión pueden eludir esto — probar y monitorizar.
Pruebas, auditoría y validación
Valide las medidas mediante pruebas automatizadas y auditorías:
- Jobs de auditoría periódicos que intenten realizar acciones no permitidas desde un Runner (¡solo en una red de prueba aislada!).
- Auditorías post-job: comprobar restos en el workspace, descriptores abiertos y procesos activos.
- Análisis de logs: buscar exfiltración de tokens o conexiones de egress inusuales.
Ejemplo de script de prueba: Post-Cleanup-Validation
#!/usr/bin/env bash
# Prüft, ob ein Job-Verzeichnis nach Cleanup noch existiert
JOB_DIR="$1"
if [ -e "$JOB_DIR" ]; then
echo "CLEANUP FAILED: $JOB_DIR still exists" >&2
ls -la "$JOB_DIR" >&2
exit 2
fi
# Prüfe auf aktive Prozesse des Runner-User
if pgrep -u runner >/dev/null; then
echo "ACTIVE PROCESSES FOUND" >&2
ps -u runner -o pid,cmd
exit 3
fi
exit 0
Errores típicos y resolución de problemas
1) Secretos accidentalmente en el registro de compilación
Causa: prints de depuración o falta de enmascaramiento. Medidas: activar el enmascaramiento de logs en CI, no exponer variables sensibles en texto plano. Automatice la comprobación de logs en busca de patrones (API-Keys, Bearer-Tokens) con un job scanner.
2) Contenedores privilegiados mal utilizados
Causa: contenedores privilegiados o montaje del socket de Docker. Medida: builds rootless, no montar sockets del host, uso de BuildKit/daemon remoto. Prueba: job intenta iniciar contenedores en el host (solo en entorno de pruebas!).
3) Claves de firma en Runner
Causa: practicidad en lugar de seguridad — los equipos almacenan claves localmente. Medida: centralizar los servicios de firma, mantener las claves solo en HSM/KMS. En caso de compromiso: rotación inmediata e invalide todas las claves potencialmente comprometidas.
Estrategia de rollback y emergencia
Introduzca los cambios de forma gradual:
- Modo monitor: solo registro, sin bloqueo.
- Cierre gradual de áreas de egress/política.
- Operación en paralelo de pools de Runner antiguos y nuevos; conmutación mediante feature-flag/ruta.
- Tokens break-glass para emergencias, de corta vida y con auditoría.
Importante: documente los pasos de reversión y pruébelos regularmente en una ejecución de prueba aislada.
Lista de verificación práctica: implementación en 90–180 minutos
- Inventariar los tokens activos y verificar permisos para cada fase del pipeline.
- Migrar trabajos no confiables a pools de runners separados o a VM efímeras.
- Ampliar los scripts de limpieza: process-kill, chown, chmod, –one-file-system, validación posterior.
- Auditar el proceso de firma y planificar el movimiento de claves a HSM/KMS.
- Crear ACLs de egreso en modo de monitorización y observar el tráfico.
- Trabajo de auditoría: intentar ejecutar desde el runner acciones no autorizadas (de forma aislada).
Conclusión
Asegurar los runners de CI/CD significa combinar practicidad con seguridad medible. Priorice la separación de credenciales por fase del pipeline (con tokens de corta duración), la limpieza garantizada del espacio de trabajo (o runners efímeros) y la firma mediante un servicio de firma o HSM/KMS. Complemente esto con RESTricciones de egreso, monitorización y pruebas de auditoría periódicas. Con una introducción por etapas, fases en modo de monitorización y rutas de retroceso probadas, la seguridad se mantiene manejable y operativamente segura.
FAQ
¿Cuál es el error más grave al asegurar los runners de CI/CD?
¿Es suficiente un contenedor como aislamiento para builds no confiables?
¿Cómo me aseguro de que la limpieza del espacio de trabajo realmente funcione?
¿Por qué no debe residir la clave privada de firma en el runner?
¿Cómo gestiono la pérdida de rendimiento por un aislamiento más estricto?
¿Qué comprobaciones debe incluir un trabajo de auditoría para runners?
Asegurar los runners de CI/CD: operación, monitorización e integración
Las medidas técnicas solo son tan buenas como su operación. Planifique el monitoreo, las métricas y las integraciones ya al introducir el endurecimiento de Runner, para que la seguridad sea repetible y medible.
Métricas y alertas importantes:
- Cleanup-Failure-Rate: proporción de Jobs en los que la Post-Job‑Validation falló. Defina un umbral y active una alarma antes de que los déficits de limpieza conduzcan a persistencia.
- Vault-Lease‑Errors y OIDC-Token‑Failures: señalan problemas con credenciales de corta duración o claims defectuosos.
- Conexiones de egress inusuales por Runner-Pool: aumentos repentinos indican exfiltración o intentos de elusión.
- Solicitudes de firma por hora y errores de firmado: las desviaciones pueden indicar pipelines comprometidas o fallos de política.
Notas de integración:
- IAM/IdP: Integre el CI como cliente OAuth/OIDC en proveedores de identidad existentes (p. ej. AD, Okta). Así, la auditoría y el ciclo de vida de usuarios permanecen controlables de forma central.
- Backends de secretos: utilice Vault/KMS de forma dinámica; automatice la renovación de leases y la rotación. Documente las rotaciones de emergencia y pruebe la ruta de revocación de claves.
- Repositorio de artefactos: complemente las políticas de firmado con atestaciones (metadatos de compilación, SBOM). Eso hace que el origen sea verificable y facilita los análisis de incidentes.
Runbook y prácticas de contingencia:
- Cree un runbook breve: pasos para aislar un Runner‑Pool, rotación de claves, interruptor de desactivación para el servicio de firmado y rollback a runners en warm‑standby.
- Realice pruebas de caos periódicas en una zona de pruebas (Cleanup-Fail, Egress-Block) y evalúe los procesos operativos frente a SLAs concretos.
Conclusión: la operación y la integración no son pensamientos secundarios. Buenas métricas, rotación automatizada y runbooks coordinados hacen que la seguridad CI/CD sea robusta y manejable en el día a día.
Para este tema también son importantes la Supply-Chain-Security y la protección de la cadena de compilación. El artículo sitúa estos aspectos de forma comprensible y muestra en qué hay que centrarse en la operación diaria.