Introducción
Comprender cómo se atacan los pipelines CI/CD es solo la mitad del panorama. El modelado de amenazas y la taxonomía de ataques nos proporcionan un mapa del campo de batalla, pero sin patrones defensivos concretos y mitigaciones de ingeniería, ese conocimiento permanece teórico. Esta guía cierra la brecha entre la concienciación y la acción.
El objetivo no es construir una fortaleza impenetrable — eso no existe. En cambio, nos enfocamos en reducir la superficie de ataque, limitar el radio de explosión cuando algo sale mal y hacer que los pipelines sean lo suficientemente resilientes como para recuperarse rápidamente. Cada control descrito aquí se relaciona con patrones de ataque del mundo real: pipelines envenenados, robo de credenciales, secuestro de dependencias y manipulación de artefactos.
Recorreremos las defensas capa por capa — desde el código fuente hasta el runtime — y luego cubriremos las capacidades de detección y respuesta a incidentes que cierran el ciclo. Ya sea que estés asegurando GitHub Actions, GitLab CI, Jenkins o cualquier otra plataforma CI/CD, los principios siguen siendo los mismos.
Defensa en Profundidad para CI/CD
Ningún control de seguridad individual es suficiente para proteger un pipeline CI/CD. Los atacantes son creativos y encontrarán la brecha en cualquier defensa de una sola capa. La única estrategia viable es la defensa en profundidad: controles superpuestos en cada etapa del ciclo de vida de entrega de software.
Mapeo de Defensas a los OWASP Top 10 CI/CD Security Risks
Los OWASP Top 10 CI/CD Security Risks proporcionan un marco estructurado para comprender qué puede salir mal. Cada riesgo — desde CICD-SEC-1 (Insufficient Flow Control Mechanisms) hasta CICD-SEC-10 (Insufficient Logging and Visibility) — requiere mitigaciones específicas. Las defensas en esta guía están organizadas para abordar estos riesgos de manera sistemática.
Los Tres Pilares: Prevención, Detección, Respuesta
- Prevención: Controles que detienen los ataques antes de que tengan éxito — protecciones de ramas, permisos mínimos, artefactos firmados, runners efímeros.
- Detección: Monitoreo y alertas que revelan anomalías — comportamiento inesperado del pipeline, deriva de configuración, nuevas dependencias, exposición de secretos.
- Respuesta: Playbooks y procedimientos para cuando las defensas fallan — revocación de credenciales, análisis del radio de explosión, verificación de integridad de artefactos, investigación forense.
Defensa en Cada Capa
Piensa en el pipeline CI/CD como una cadena de límites de confianza:
- Fuente: Donde el código y la configuración ingresan al pipeline
- Build: Donde el código se compila, se prueba y se empaqueta
- Artefacto: Donde los resultados del build se almacenan y distribuyen
- Deploy: Donde los artefactos llegan a la infraestructura de producción
- Runtime: Donde el software desplegado se ejecuta y se monitorea
Cada capa tiene amenazas distintas y requiere defensas distintas. El compromiso en una capa no debería propagarse automáticamente a la siguiente.
Defensas de la Capa de Fuente — Protección de las Entradas del Pipeline
La capa de fuente es donde comienzan la mayoría de los ataques a CI/CD. Un atacante que puede modificar código, definiciones de pipelines o archivos de configuración controla lo que ejecuta el pipeline. Las defensas de la capa de fuente aseguran que solo los cambios autorizados, revisados y verificados ingresen al pipeline.
Reglas de Protección de Ramas
La protección de ramas es la primera línea de defensa. Como mínimo, las ramas main y de release deben aplicar:
- Pull request reviews obligatorios: Sin push directo a ramas protegidas. Todos los cambios pasan por revisión de código.
- Status checks obligatorios: El CI debe pasar antes del merge. Esto previene la fusión de código roto o malicioso que evade las pruebas.
- Sin force pushes: El force push reescribe el historial y puede usarse para eliminar evidencia de commits maliciosos.
- Historial lineal obligatorio: Previene los merge commits que pueden ocultar cambios maliciosos en diffs complejos.
CODEOWNERS para Rutas Sensibles
No todos los archivos en un repositorio conllevan el mismo riesgo. Las definiciones de pipelines, las plantillas de infrastructure-as-code y las configuraciones de contenedores son objetivos de alto valor. Usa CODEOWNERS para requerir revisión de equipos específicos para rutas sensibles:
# .github/CODEOWNERS
# Pipeline definitions require security team review
.github/workflows/ @org/security-team
.gitlab-ci.yml @org/security-team
Jenkinsfile @org/security-team
# Infrastructure as code
terraform/ @org/platform-team @org/security-team
pulumi/ @org/platform-team @org/security-team
# Container definitions
Dockerfile* @org/security-team
docker-compose*.yml @org/security-team
# Dependency manifests
package.json @org/security-team
requirements.txt @org/security-team
go.sum @org/security-team
Commits Firmados y Verificación
La firma de commits proporciona prueba criptográfica de autoría. Sin ella, un atacante que comprometa el token de acceso de un desarrollador puede enviar commits que parecen provenir de cualquier persona. Habilita la verificación de firma de commits en ramas protegidas para asegurar que cada commit esté firmado con una clave GPG o SSH verificada.
# Configure Git to sign commits with SSH key
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub
git config --global commit.gpgsign true
# Verify a commit signature
git verify-commit HEAD
Políticas de Revisión de PR
La revisión de código es un control humano, y necesita barandillas:
- Sin auto-aprobación: El autor de un PR nunca debería poder aprobar sus propios cambios.
- Revisores obligatorios del equipo de seguridad para cambios en archivos de pipeline, configuración de secretos o manifiestos de despliegue.
- Descartar revisiones obsoletas: Si se envían nuevos commits después de la aprobación, las aprobaciones anteriores deben descartarse para forzar una nueva revisión.
- Requerir revisión de code owners: Combina esto con CODEOWNERS para aplicar requisitos de revisión específicos del dominio.
Limitación de Triggers del Pipeline
No todos los eventos deben activar una ejecución completa del pipeline, especialmente una que tenga acceso a secretos:
- Restricciones de forks: Los PRs desde forks deben ejecutarse en un contexto restringido sin acceso a los secretos del repositorio.
- Permisos de contribuidores: Solo los colaboradores con acceso de escritura deberían poder activar workflows que acceden a recursos sensibles.
- Aprobación para contribuidores primerizos: Requerir aprobación manual antes de ejecutar pipelines para nuevos contribuidores.
Defensas de la Capa de Build — Asegurando el Proceso de Build
La capa de build es donde el código se convierte en ejecutable. Un compromiso aquí significa que un atacante puede inyectar lógica maliciosa en tus artefactos sin modificar el código fuente. Las defensas de la capa de build se centran en el aislamiento, la efimeralidad y el privilegio mínimo.
Runners Efímeros
Los runners CI persistentes acumulan estado: credenciales en caché, archivos sobrantes de builds anteriores, variables de entorno que se filtran entre jobs. Los runners efímeros eliminan esta clase de riesgo por completo al aprovisionar una VM o contenedor nuevo para cada job y destruirlo inmediatamente después.
# GitHub Actions: Self-hosted ephemeral runner with actions-runner-controller
apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:
name: ephemeral-runners
spec:
replicas: 5
template:
spec:
ephemeral: true
repository: your-org/your-repo
labels:
- self-hosted
- ephemeral
- linux
dockerdWithinRunnerContainer: false
image: ghcr.io/actions/actions-runner:latest
resources:
limits:
cpu: "2"
memory: "4Gi"
Entornos de Build Aislados
Incluso con runners efímeros, los builds que comparten cachés o namespaces de red pueden filtrar información entre jobs. Asegura:
- Sin cachés compartidos entre builds no confiables: El envenenamiento de caché es un vector de ataque real. Aísla los cachés por rama o por PR.
- Pools de runners separados: Los runners de despliegue a producción nunca deben compartirse con los runners de validación de PRs.
- Aislamiento de contenedores: Usa contenedores rootless o microVMs (Firecracker, gVisor) para un aislamiento más fuerte que Docker estándar.
Restricciones de Red Durante los Builds
Un paso de build comprometido con acceso de red sin restricciones puede exfiltrar secretos a infraestructura controlada por el atacante. Restringe el acceso de red saliente:
- Sin internet saliente: La opción más estricta. Todas las dependencias deben provenir de mirrors internos o imágenes pre-cacheadas.
- Solo dominios en lista blanca: Si el acceso a internet es necesario, restríngelo a registros y repositorios de paquetes conocidos.
- Filtrado basado en DNS: Usa políticas DNS para bloquear el acceso a dominios no autorizados durante los builds.
# Kubernetes NetworkPolicy for CI runner pods
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ci-runner-egress-restricted
namespace: ci-runners
spec:
podSelector:
matchLabels:
role: ci-runner
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/8 # Internal network only
ports:
- protocol: TCP
port: 443 # HTTPS to internal registries
- protocol: TCP
port: 53 # DNS
- protocol: UDP
port: 53 # DNS
Imágenes de Build Mínimas
Cada herramienta instalada en una imagen de build es una superficie de ataque potencial. Reduce las imágenes de build al mínimo necesario:
- Usa imágenes distroless o basadas en Alpine como bases de build.
- Elimina shells, gestores de paquetes y utilidades de red de las imágenes de build de producción cuando sea posible.
- Fija los digests de imagen, no los tags, para prevenir ataques a la cadena de suministro basados en tags.
# Pin by digest, not by tag
FROM golang:1.22@sha256:a3b21c5d8e... AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o /app/binary
# Use distroless for the final image
FROM gcr.io/distroless/static-debian12@sha256:f4e8b1c2d9...
COPY --from=builder /app/binary /binary
ENTRYPOINT ["/binary"]
Desactivar Modos de Debug en Pipelines de Producción
El logging de debug y la salida detallada son invaluables durante el desarrollo pero peligrosos en pipelines de producción. Pueden filtrar secretos, rutas internas y detalles de infraestructura. Asegúrate de que ACTIONS_STEP_DEBUG, CI_DEBUG_TRACE y flags equivalentes estén desactivados en las configuraciones de pipelines de producción.
Defensas de Credenciales e Identidad — Limitando lo que los Pipelines Pueden Acceder
Las credenciales son el objetivo más valioso en cualquier pipeline CI/CD. Un atacante que obtenga una clave de acceso a la nube, un token de despliegue o un secreto de API puede pivotar mucho más allá del pipeline en sí. Las defensas de credenciales se centran en minimizar lo que existe, lo que se puede acceder y por cuánto tiempo.
Permisos Mínimos de Tokens
El GITHUB_TOKEN predeterminado en GitHub Actions tiene permisos amplios. Siempre restríngelo al mínimo requerido:
# GitHub Actions: Restrict default token permissions
permissions:
contents: read
packages: read
id-token: write # Only if using OIDC
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- run: make build
deploy:
runs-on: ubuntu-latest
needs: build
permissions:
contents: read
id-token: write # For OIDC authentication
steps:
- name: Authenticate to cloud
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/deploy-role
aws-region: us-east-1
OIDC y Workload Identity
Los secretos de larga duración almacenados en sistemas CI/CD son bombas de tiempo. Reemplázalos con federación de identidad de carga de trabajo basada en OIDC siempre que sea posible:
- GitHub Actions a AWS: Usa
aws-actions/configure-aws-credentialscon asunción de rol OIDC. - GitHub Actions a GCP: Usa
google-github-actions/authcon Workload Identity Federation. - GitHub Actions a Azure: Usa
azure/logincon credenciales federadas. - GitLab CI a AWS/GCP/Azure: Usa el token OIDC nativo de GitLab (
CI_JOB_JWT_V2) con federación del proveedor de nube.
Con OIDC, la plataforma CI/CD emite un JWT de corta duración, y el proveedor de nube lo intercambia por credenciales temporales. No se almacenan secretos estáticos en ningún lugar.
Credenciales por Entorno y por Etapa
Un único conjunto de credenciales compartido entre todos los entornos es un radio de explosión catastrófico. Segmenta las credenciales:
- Desarrollo, staging y producción deben usar cuentas de servicio separadas con permisos separados.
- Las etapas de build no deben tener acceso a las credenciales de despliegue.
- Las etapas de prueba deben usar infraestructura de prueba aislada, no entornos compartidos.
Sin Secretos en Workflows de PR/Fork
Los pull requests desde forks nunca deben tener acceso a los secretos del repositorio. Esta es una mala configuración común que permite a los atacantes exfiltrar secretos enviando un PR malicioso. En GitHub Actions, usa pull_request (no pull_request_target) para código no confiable, y nunca pases secretos a pasos que ejecuten código del PR.
Integración con Vault y Secretos Dinámicos
Para credenciales que no pueden usar OIDC (contraseñas de bases de datos, claves API para servicios de terceros), usa un gestor de secretos como HashiCorp Vault con secretos dinámicos y de corta duración:
# HashiCorp Vault: Generate short-lived database credentials
vault read database/creds/ci-readonly
# Returns:
# Key Value
# --- -----
# lease_id database/creds/ci-readonly/abc123
# lease_duration 1h
# username v-ci-readonly-xyz789
# password A1B2-C3D4-E5F6-G7H8
Los secretos dinámicos se generan bajo demanda, están delimitados a la identidad solicitante y se revocan automáticamente cuando expiran. Incluso si se filtran, la ventana de exposición se mide en minutos, no en meses.
Auditoría de Todos los Accesos a Secretos
Cada recuperación de secreto debe generar una entrada en el registro de auditoría. Si tu gestor de secretos no registra los accesos, no tienes forma de investigar un compromiso. Asegúrate de que los registros capturen: quién accedió a qué, cuándo, desde qué ejecución de pipeline y desde qué dirección IP.
Defensas de la Capa de Artefactos — Asegurando la Integridad de las Salidas
Los artefactos de build — imágenes de contenedores, binarios, paquetes — son el puente entre tu pipeline y producción. Si un atacante puede manipular los artefactos después de construidos, todas las defensas anteriores se vuelven irrelevantes. Las defensas de la capa de artefactos aseguran integridad, procedencia e inmutabilidad.
Firma de Todos los Artefactos con Sigstore/Cosign
La firma de artefactos proporciona prueba criptográfica de que un artefacto fue producido por tu pipeline y no ha sido modificado desde entonces. Cosign de Sigstore hace práctica la firma sin claves:
# Sign a container image using Cosign (keyless, OIDC-based)
cosign sign --yes ghcr.io/your-org/your-app:v1.2.3@sha256:abc123...
# Verify the signature
cosign verify \
--certificate-identity=https://github.com/your-org/your-app/.github/workflows/build.yml@refs/heads/main \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
ghcr.io/your-org/your-app:v1.2.3@sha256:abc123...
Con la firma sin claves, la clave de firma es efímera y está vinculada a la identidad OIDC del workflow CI/CD. No hay una clave de firma de larga duración que robar.
Generación y Almacenamiento de Provenance SLSA
SLSA (Supply-chain Levels for Software Artifacts) provenance registra cómo, dónde y por quién se construyó un artefacto. En SLSA Level 3, la provenance es generada por la propia plataforma de build y no puede ser falsificada por el proceso de build:
# GitHub Actions: Generate SLSA provenance for container images
- uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
with:
image: ghcr.io/your-org/your-app
digest: ${{ steps.build.outputs.digest }}
secrets:
registry-username: ${{ github.actor }}
registry-password: ${{ secrets.GITHUB_TOKEN }}
Almacenamiento Inmutable de Artefactos
Los artefactos publicados nunca deben sobrescribirse. Si un atacante puede reemplazar una versión publicada, puede inyectar código malicioso en cada despliegue que haga referencia a esa versión. Configura tus registros para inmutabilidad:
- Registros de contenedores: Habilita la inmutabilidad de tags (ECR, GCR, ACR todos lo soportan).
- Registros de paquetes: Previene la re-publicación de versiones existentes.
- Almacenamiento de binarios: Usa políticas de escritura única (S3 Object Lock, políticas de retención de GCS).
Generación de SBOM y Attestation
Un Software Bill of Materials (SBOM) lista cada componente en tu artefacto. Generar un SBOM en tiempo de build y atestiguarlo junto al artefacto crea un inventario verificable para la gestión de vulnerabilidades:
# Generate SBOM with Syft and attest with Cosign
syft ghcr.io/your-org/your-app:v1.2.3 -o spdx-json > sbom.spdx.json
cosign attest --predicate sbom.spdx.json --type spdxjson \
ghcr.io/your-org/your-app:v1.2.3@sha256:abc123...
Admission Controllers para Verificación de Firmas
Firmar artefactos solo es útil si verificas las firmas antes del despliegue. Usa admission controllers de Kubernetes para aplicar esto automáticamente:
# Kyverno: Require signed images
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-signed-images
spec:
validationFailureAction: Enforce
background: false
rules:
- name: verify-cosign-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "ghcr.io/your-org/*"
attestors:
- entries:
- keyless:
issuer: "https://token.actions.githubusercontent.com"
subject: "https://github.com/your-org/*"
Con esta política en vigor, cualquier imagen de contenedor que carezca de una firma Cosign válida de tus workflows de GitHub Actions será rechazada en el momento de admisión — antes de que se ejecute en tu clúster.
Defensas de la Capa de Despliegue — Controlando lo que Llega a Producción
La capa de despliegue es la última puerta antes de que los cambios lleguen a producción. Las defensas aquí aseguran que solo los artefactos verificados y aprobados sean desplegados, y que el proceso de despliegue en sí sea controlado y auditable.
Aprobaciones Manuales Obligatorias
Para despliegues en producción, los pipelines automatizados deben pausarse y requerir aprobación humana explícita. Esto proporciona un punto de verificación final donde un humano puede confirmar que el cambio es esperado, probado y autorizado.
# GitHub Actions: Environment with required reviewers
jobs:
deploy-production:
runs-on: ubuntu-latest
environment:
name: production
url: https://your-app.example.com
steps:
- name: Deploy to production
run: ./deploy.sh production
En la configuración del repositorio de GitHub, configura el entorno «production» para requerir aprobación de revisores designados antes de que el job proceda.
GitOps con Despliegue Pull-Based
Los pipelines CI/CD tradicionales hacen push a producción: el pipeline tiene credenciales para modificar la infraestructura de producción. Esto es una gran superficie de ataque. GitOps con despliegue pull-based invierte el modelo:
- El pipeline actualiza un repositorio Git con el estado deseado (image tags, manifiestos).
- El clúster ejecuta un controlador (Flux, ArgoCD) que observa el repositorio Git y extrae los cambios.
- El pipeline nunca tiene acceso directo al clúster. El clúster extrae de Git, y Git es la única fuente de verdad.
# Flux: GitRepository and Kustomization for pull-based deployment
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: app-manifests
namespace: flux-system
spec:
interval: 1m
url: https://github.com/your-org/app-manifests
ref:
branch: main
secretRef:
name: git-credentials
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: app-production
namespace: flux-system
spec:
interval: 5m
path: ./environments/production
prune: true
sourceRef:
kind: GitRepository
name: app-manifests
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: your-app
namespace: production
Despliegues Canary y Rollback Automatizado
Incluso con todas las defensas anteriores, un despliegue puede introducir problemas. Los despliegues canary limitan la exposición al desplegar cambios a un pequeño porcentaje del tráfico primero. Si las métricas se degradan, el rollback automatizado revierte el cambio antes de que afecte a todos los usuarios.
- Usa herramientas de entrega progresiva como Flagger, Argo Rollouts o funcionalidades canary nativas del proveedor de nube.
- Define criterios de éxito claros: tasa de errores, latencia, métricas de saturación.
- Automatiza los triggers de rollback — no dependas de humanos para notar y reaccionar a tiempo.
Congelación de Despliegues
Durante incidentes activos, ventanas de mantenimiento o períodos de alto tráfico, los despliegues deben congelarse. Implementa políticas de congelación de despliegues que prevengan despliegues iniciados por pipelines durante ventanas especificadas, y asegura que solo los comandantes de incidentes designados puedan anular la congelación.
Detección y Monitoreo — Saber Cuándo Algo Está Mal
La prevención eventualmente fallará. Las capacidades de detección determinan si detectas un compromiso en minutos o en meses. El monitoreo de CI/CD es un punto ciego para muchas organizaciones — su SIEM ingiere logs de aplicaciones e infraestructura pero ignora completamente la telemetría del pipeline.
Detección de Anomalías en la Ejecución del Pipeline
Establece líneas base para el comportamiento normal del pipeline y genera alertas sobre desviaciones:
- Tiempos de ejecución inusuales: Un build que normalmente toma 5 minutos y de repente toma 30 minutos podría indicar cryptomining o exfiltración de datos.
- Pasos inesperados: Nuevos pasos en el pipeline que aparecen sin cambios correspondientes en PRs.
- Ejecución fuera de horario: Ejecuciones de pipelines activadas fuera del horario laboral normal por cuentas inusuales.
- Picos de autenticación fallida: Múltiples intentos fallidos de acceso a secretos desde una sola ejecución de pipeline.
Alertas de Diff de Dependencias
Las nuevas dependencias añadidas en PRs deben activar revisión automatizada y alertas. Una herramienta de diff de dependencias puede:
- Marcar nuevas dependencias añadidas en un PR para revisión manual.
- Verificar nuevas dependencias contra bases de datos de paquetes maliciosos conocidos.
- Verificar que las versiones de dependencias coincidan con las de lockfiles conocidos como buenos.
- Alertar sobre dependencias con fechas de publicación muy recientes (potencial typosquatting).
Escaneo de Secretos
Los secretos se filtran a través de commits, logs y artefactos. Combina múltiples enfoques de escaneo:
- Pre-commit hooks: Herramientas como
gitleaksotrufflehogcapturan secretos antes de que entren al repositorio. - Escaneo en el pipeline: Escanea las salidas del build y los logs en busca de credenciales expuestas accidentalmente.
- GitHub secret scanning / GitLab secret detection: Escaneo nativo de la plataforma que cubre eventos de push y commits históricos.
- Alertas del programa de partners: El programa de partners de secret scanning de GitHub notifica a los proveedores de servicios cuando sus tokens están expuestos, permitiendo la revocación automática.
# Pre-commit hook with gitleaks
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
Monitoreo de Deriva de Configuración
Las definiciones de pipelines deben cambiar a través del proceso normal de PR. Monitorea cambios inesperados:
- Alerta cuando los archivos de workflow, configuraciones de CI o manifiestos de despliegue cambian fuera de PRs aprobados.
- Rastrea los cambios de permisos del pipeline a lo largo del tiempo.
- Detecta nuevos secretos de pipeline que se añaden sin solicitudes de cambio correspondientes.
Integración SIEM para Logs de Auditoría de CI/CD
Reenvía los logs de auditoría de CI/CD a tu SIEM junto con los logs de aplicaciones e infraestructura. Las fuentes de logs clave incluyen:
- GitHub Audit Log (nivel de organización y empresa)
- GitLab Audit Events
- Logs de sistema y de build de Jenkins
- Logs de auditoría del proveedor de nube para llamadas API iniciadas por el pipeline (CloudTrail, Cloud Audit Logs, Azure Activity Log)
Correlaciona la actividad del pipeline con cambios en la infraestructura de nube. Si una ejecución de pipeline coincide con modificaciones inesperadas de políticas IAM o creación de recursos, esa es una alerta de alta prioridad.
Respuesta a Incidentes para CI/CD — Cuando las Defensas Fallan
Cuando se detecta — o se sospecha — un compromiso de CI/CD, la velocidad importa. El atacante puede aún tener acceso activo, y cada minuto de retraso amplía el radio de explosión. Un playbook de respuesta a incidentes preparado para escenarios específicos de CI/CD es esencial.
Acciones Inmediatas: Contener el Compromiso
- Revocar credenciales comprometidas inmediatamente. Rota todos los secretos a los que el pipeline comprometido tenía acceso. Esto incluye credenciales de proveedores de nube, tokens de API, contraseñas de bases de datos y los propios tokens de la plataforma CI/CD.
- Desactivar el pipeline comprometido. Previene ejecuciones adicionales hasta que la investigación esté completa.
- Poner en cuarentena los runners afectados. Si usas runners persistentes, aíslalos de la red para análisis forense.
Análisis del Radio de Explosión
Determina a qué pudo haber accedido el atacante:
- ¿Qué secretos estaban disponibles para el job comprometido?
- ¿A qué recursos de nube podían acceder esas credenciales?
- ¿Qué artefactos se produjeron durante el período comprometido?
- ¿A qué entornos se desplegó desde el pipeline comprometido?
Verificación de Integridad de Artefactos
Verifica si los artefactos publicados fueron manipulados:
- Verifica las firmas en todos los artefactos publicados durante la ventana comprometida.
- Compara los checksums de artefactos contra builds conocidos como buenos.
- Si la integridad del artefacto no puede verificarse, reconstruye y republica desde commits de fuente conocidos como buenos.
- Notifica a los consumidores downstream si se distribuyeron artefactos potencialmente comprometidos.
Investigación Forense
Recopila evidencia de múltiples fuentes:
- Logs de runners: ¿Qué comandos se ejecutaron? ¿Qué conexiones de red se realizaron?
- Logs de auditoría de API: ¿Qué llamadas API hizo el atacante usando credenciales del pipeline?
- Historial de Git: ¿Se modificaron commits o ramas? Verifica force pushes o reescritura del historial.
- Logs de auditoría de la nube: ¿Qué cambios de infraestructura realizaron las cuentas de servicio del pipeline?
Recuperación Post-Incidente
Después de la contención e investigación, restaura las operaciones seguras:
- Rota todos los secretos que eran accesibles al pipeline comprometido, incluso si no hay evidencia de que fueron exfiltrados.
- Revisa y ajusta los permisos del pipeline. El incidente probablemente reveló alcances de permisos más amplios de lo necesario.
- Actualiza las reglas de monitoreo basándote en los indicadores de compromiso descubiertos durante la investigación.
- Realiza un post-mortem sin culpa enfocado en qué cambios sistémicos previenen la recurrencia.
Plantilla de Playbook de Respuesta a Incidentes CI/CD
## CI/CD Security Incident Playbook
### Phase 1: Detection & Triage (0-15 minutes)
- [ ] Confirm the alert is a true positive
- [ ] Classify severity (P1: active compromise, P2: suspected compromise, P3: policy violation)
- [ ] Notify the incident commander and security team
### Phase 2: Containment (15-60 minutes)
- [ ] Revoke compromised credentials
- [ ] Disable affected pipelines
- [ ] Isolate affected runners
- [ ] Block attacker's access (revoke tokens, disable accounts)
### Phase 3: Investigation (1-24 hours)
- [ ] Collect runner logs, audit logs, git history
- [ ] Determine blast radius (credentials, artifacts, deployments)
- [ ] Identify attack vector (how did the attacker get in?)
- [ ] Check artifact integrity for the compromised period
### Phase 4: Recovery (24-72 hours)
- [ ] Rotate all potentially compromised secrets
- [ ] Rebuild and republish affected artifacts from known-good source
- [ ] Redeploy affected environments from verified artifacts
- [ ] Restore pipeline operations with tightened controls
### Phase 5: Post-Incident (1-2 weeks)
- [ ] Conduct blameless post-mortem
- [ ] Document lessons learned and update this playbook
- [ ] Implement systemic improvements to prevent recurrence
- [ ] Update detection rules based on IOCs discovered
Conclusión
La seguridad de CI/CD no es una lista de verificación que completas una vez y olvidas. Es una práctica de ingeniería continua que evoluciona con tus pipelines, tu infraestructura y el panorama de amenazas. Los atacantes seguirán apuntando a la cadena de suministro de software porque ofrece alto apalancamiento — un solo pipeline comprometido puede afectar cada despliegue, cada entorno y cada cliente.
Las defensas en esta guía están organizadas por capa, pero los puntos de inicio de mayor impacto cruzan todas las capas:
- Runners efímeros eliminan clases enteras de ataques de persistencia y filtración de estado.
- Permisos mínimos (alcance de tokens, OIDC, credenciales por entorno) limitan lo que un atacante puede hacer incluso después de obtener acceso al pipeline.
- Artefactos firmados con control de admisión aseguran que los artefactos manipulados no puedan llegar a producción.
- Detección y registro de auditoría cierran la brecha de visibilidad que permite que los compromisos pasen desapercibidos durante meses.
Comienza con estos controles de alto impacto. Añade defensas adicionales a medida que tu programa de seguridad madure. Y siempre asume que tu pipeline será un objetivo — porque lo será.
En el próximo artículo de esta serie, recorreremos la implementación de estas defensas en un pipeline real de GitHub Actions, con un ejemplo funcional completo que puedes adaptar para tus propios repositorios.