StackPractices
intermediate Por Mathias Paulenko

Plantilla de Seguridad de Pipeline CI/CD

Una plantilla para asegurar pipelines de compilación y despliegue contra filtraciones de credenciales, manipulación, ataques a la cadena de suministro y despliegues no autorizados.

Descripción General

Los pipelines CI/CD son un objetivo de alto valor para los atacantes porque tienen acceso al código fuente, secretos de compilación y rutas de despliegue a producción. Un pipeline comprometido puede introducir malware, exfiltrar datos o desplegar cambios no autorizados. Esta plantilla define controles para proteger la integridad del código, la seguridad de los runners, los secretos y las aprobaciones de despliegue. Para el lado estratégico, consulta la guía de seguridad CI/CD; para la mitad del problema que son los secretos, la receta de gestión de secretos en Docker cubre el ángulo de contenedores.

Cuándo Usar

  • Al configurar una nueva plataforma CI/CD.
  • Al revisar o mejorar un pipeline existente.
  • Al prepararse para una auditoría de seguridad de la cadena de suministro.
  • Después de un compromiso del sistema de compilación o un despliegue no autorizado.
  • Al integrar controles DevSecOps en los flujos de trabajo de ingeniería.

Prerequisitos

  • Un sistema de control de versiones con protección de ramas y registro de auditoría.
  • Una plataforma CI/CD como GitHub Actions, GitLab CI, Azure DevOps o Jenkins.
  • Una solución de gestión de secretos para credenciales de pipeline.
  • Un proceso de revisión y aprobación de código antes de integrar cambios.
  • Responsables por parte de ingeniería de plataforma, seguridad y gestión de releases.

Solución

Plantilla

1. Seguridad del Control de Código

ControlRequisitoVerificación
Protección de ramasRevisiones requeridas antes de integrar a mainConfiguración del repositorio
Commits firmadosRequerir commits verificados para cuentas privilegiadasConfiguración de Git
Control de accesoAcceso de mínimo privilegio a repositoriosRevisión de RBAC
Registro de auditoríaTodos los pushes, merges y cambios de permisos registradosLogs de la plataforma
Dependencias fijadasLockfiles y versiones fijas para compilaciones reproduciblesArchivos del repositorio
Escaneo de secretosDetección automatizada de secretos en commitsPre-commit hooks + CI

2. Configuración del Pipeline

ControlRequisitoVerificación
Definiciones inmutables de pipelinePipelines almacenados como código y revisadosArchivos del repositorio
Sin secretos en códigoSecretos cargados desde vault, variables de CI u OIDCEscaneo de secretos
Validación de entradaParámetros del pipeline validados y sanitizadosRevisión de código
Aislamiento de runners self-hostedRunners de producción aislados de los de desarrolloConfiguración de runners
Runners efímerosRunner nuevo por build para reducir persistenciaConfiguración de runners
Provenance del pipelineProvenance SLSA generada para los artefactosHerramienta de atestación

3. Gestión de Secretos

Tipo de SecretoAlmacenamientoRotaciónAlcance
Credenciales de nubeVault externo u OIDC90 díasPor entorno
Tokens de registry de contenedoresVault o tokens de CI de corta duración90 díasPor pipeline
Claves de firmaHardware-backed o KMS180 díasCuentas de servicio limitadas
Claves de APIVault o gestor de secretos90 díasPermisos mínimos requeridos
Contraseñas de base de datosSecretos dinámicos de vault24 horasPor ejecución de pipeline

4. Seguridad de la Compilación

ControlRequisitoVerificación
Escaneo de dependenciasTodas las dependencias escaneadas por CVEs conocidosEscáner en CI
Análisis estáticoSAST en cada pull requestJob de CI
Escaneo de imágenes de contenedorImagen base y capas escaneadas antes del pushEscaneo del registry
Compilaciones reproduciblesEl mismo código fuente produce el mismo artefactoVerificación de build
Firma de artefactosTodos los artefactos firmados con identidad de buildVerificación de firma
Generación de SBOMLista de materiales generada por buildOutput de CI

5. Seguridad del Despliegue

ControlRequisitoVerificación
Puertas de despliegueAprobación manual o automatizada antes de producciónReglas del pipeline
Separación de entornosCredenciales de producción no disponibles en desarrolloAlcance de secretos
Plan de rollbackTrigger de rollback automático ante fallosDefinición del pipeline
Despliegues inmutablesArtefactos desplegados por referencia, no reconstruidosLogs de despliegue
Detección de driftCambios no autorizados en producción detectadosHerramienta de monitoreo
TrazabilidadQuién desplegó qué, cuándo y por quéLogs de despliegue

6. Respuesta a Incidentes

EscenarioRespuestaResponsable
Secreto filtradoRotar secreto, revocar tokens, auditar usoEquipo de seguridad
Commit maliciosoRevertir, investigar, revocar credencialesEquipo de plataforma
Runner comprometidoTerminar runner, reconstruir, revisar logsEquipo de plataforma
Despliegue no autorizadoRollback, congelar pipeline, auditarRelease manager
Artefacto manipuladoBloquear despliegue, rastrear provenanceEquipo de seguridad

Explicación

La seguridad del pipeline es seguridad de la cadena de suministro aplicada a la máquina que publica tu código. Protege el código fuente, la compilación y la ruta de despliegue y habrás cortado la mayoría de las vías por las que código malicioso llega a producción. La plantilla mapea cada control a cómo verificarlo, así que también sirve como artefacto de auditoría.

flowchart diagram: subgraph UNTRUSTED[

Configuración de Seguridad para GitHub Actions

name: Secure CI Pipeline
on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

permissions:
  contents: read
  packages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/ci-role
          aws-region: us-east-1
          # No static keys - OIDC only

      - name: Build and sign
        uses: sigstore/cosign-installer@v3
      - run: |
          cosign sign-blob --yes artifact.tar.gz

      - name: Generate SBOM
        uses: anchore/sbom-action@v0
        with:
          format: spdx-json
          output-file: sbom.spdx.json

      - name: Scan dependencies
        uses: github/codeql-action/init@v3
      - run: npm audit --audit-level=high
      - uses: github/codeql-action/analyze@v3

Ejemplo de Provenance SLSA

{
  "_type": "https://in-toto.io/Statement/v1",
  "subject": [
    {
      "name": "artifact.tar.gz",
      "digest": { "sha256": "abc123..." }
    }
  ],
  "predicateType": "https://slsa.dev/provenance/v1",
  "predicate": {
    "builder": { "id": "github-actions" },
    "buildType": "https://github.com/actions/runner",
    "invocation": {
      "configSource": {
        "uri": "git+https://github.com/org/repo",
        "digest": { "sha1": "commit-hash" }
      }
    },
    "materials": [
      { "uri": "git+https://github.com/org/repo", "digest": { "sha1": "commit-hash" } }
    ]
  }
}

Checklist de Auditoría de Seguridad del Pipeline

ControlVerificadoNotas
Sin secretos de larga duración en CI
OIDC para autenticación en la nube
Actions fijadas a SHA
Permisos mínimos por job
Protección de rama en main
Artefactos firmados verificados
SBOM generado por build
Escaneo de dependencias en el pipeline
Runners aislados por entorno
Retención de logs de auditoría > 90 días

Ataques Reales al Pipeline

Estos controles no son higiene hipotética: mapean a incidentes que ya ocurrieron.

SolarWinds (2020). Los atacantes comprometieron el propio sistema de build y publicaron una actualización de Orion con backdoor a miles de organizaciones, firmada y distribuida por el canal oficial. Es el caso canónico de por qué importan la provenance del build y los builds reproducibles: el artefacto malicioso pasó todas las verificaciones del lado del consumidor porque el compromiso ocurrió aguas arriba.

Codecov (2021). Un script bash uploader modificado dentro de las herramientas de CI de Codecov exfiltró variables de entorno, incluyendo secretos, de miles de pipelines de clientes durante dos meses. El control exacto que lo habría detectado: dependencias fijadas con hash y alertas sobre tráfico saliente inesperado desde los runners.

tj-actions/changed-files (2025). Un GitHub Action popular fue comprometido y publicó una release maliciosa que filtró secretos de CI en los logs de workflow. Los equipos que fijaban las actions a SHAs de commit eran inmunes por defecto. Los tags se movieron al commit malicioso; los SHAs no.

Servidor git de PHP (2021). Los atacantes pushearon commits con backdoor directamente al repositorio propio de PHP, suplantando a maintainers del core. La respuesta fue instructiva: PHP abandonó su git self-hosted y se movió a GitHub con 2FA obligatorio — a veces la solución es externalizar la frontera de confianza a una plataforma con mejores controles.

El patrón en los cuatro: el pipeline es confiable por defecto, y esa confianza es exactamente lo que explotan los atacantes. Una plantilla como esta existe para hacer la confianza explícita y verificable en lugar de asumida.

Variantes

  • Checklist de seguridad para GitHub Actions: enfocado en fijar actions, permisos de workflow y workflows reutilizables.
  • Plantilla de seguridad para GitLab CI: incluye scopes de tokens de job CI/CD, runners protegidos y pipelines de compliance.
  • Plantilla de endurecimiento de Jenkins: cubre gestión de plugins, aislamiento de agentes y sandboxing de Groovy.
  • Pipeline nativo de contenedores: enfatiza firma de imágenes, escaneo del registry y admission de Kubernetes.
  • Pipeline de alta compliance: añade SLSA Nivel 3, doble aprobación y SBOMs firmados para entornos regulados.

Lo que funciona

  • Almacenar las definiciones del pipeline como código y revisarlas como código de aplicación.
  • Usar credenciales de corta duración y OIDC en lugar de secretos de larga duración.
  • Escanear dependencias antes de integrar y antes de desplegar.
  • Firmar artefactos y verificar firmas antes del despliegue.
  • Separar los entornos de build y producción física o lógicamente.
  • Requerir aprobación humana para despliegues a producción.
  • Generar y retener SBOMs para cada release.
  • Monitorear la actividad del pipeline buscando comportamiento inusual.

Errores Comunes

  • Almacenar secretos en variables de entorno o archivos del pipeline.
  • Usar actions de terceros sin fijarlas ni revisarlas.
  • Permitir que cualquier rama despliegue a producción.
  • Correr cargas de producción y desarrollo en el mismo runner.
  • Saltarse los escaneos de seguridad en despliegues de hotfix.
  • No rotar las credenciales del pipeline tras un compromiso.
  • Confiar en artefactos sin verificación de firma.

Troubleshooting

  • Un secreto aparece en un log de build: rótalo inmediatamente y asume que está comprometido en el momento en que se imprime. Luego encuentra la ruta de código que lo registró (normalmente un echo sin enmascarar o un volcado de error) y añade el valor a la lista de enmascaramiento de logs.
  • Un escaneo de dependencias falla por un CVE transitivo que no puedes arreglar: comprueba si la ruta de código vulnerable es realmente alcanzable. Si no lo es, documenta el riesgo aceptado con fecha de revisión y fija una excepción; si lo es, sube la dependencia padre o aplica un parche vendorizado.
  • La verificación de provenance falla al desplegar: no despliegues. Una atestación que no coincide significa que el artefacto no es lo que CI construyó. Compara el digest con el almacén de artefactos de CI y averigua dónde ocurrió la sustitución antes de publicar nada.
  • Una puerta de aprobación es ignorada: revisa quién tiene derechos de administrador sobre las reglas de protección del entorno. Las puertas fallan abiertas más a menudo por permisos mal configurados que por atacantes.
  • Un action de terceros publica una release maliciosa: si fijas a SHAs de commit esto no puede alcanzarte — los tags se mueven, los SHAs no. Si estás en un tag, fija el SHA bueno conocido inmediatamente y audita lo que corrió en la ventana.

Ver También

Código complementario: recursos de seguridad de pipeline CI/CD: la plantilla de controles, el workflow endurecido, el ejemplo de provenance SLSA y el checklist de auditoría de esta página.

Preguntas frecuentes

¿Cuál es el riesgo más grande en CI/CD?

El robo de credenciales desde un runner o un archivo de pipeline — una vez que un atacante tiene tus claves de despliegue, no necesita tocar tu aplicación en absoluto; simplemente publica su propio código como si fuera tuyo.

¿Cómo balanceamos seguridad con despliegues rápidos?

Automatiza los chequeos y mantenlos rápidos, luego reserva la aprobación humana solo para producción. El escaneo shift-left da feedback a los desarrolladores en minutos, que es lo que hace que la puerta de seguridad sea algo que realmente mantendrán.

¿Qué es la provenance SLSA?

SLSA es un framework para seguridad de la cadena de suministro. La provenance registra cómo se construyó un artefacto — repositorio fuente, comando de build, dependencias — así que un artefacto manipulado o reconstruido no coincide con su propio rastro.

¿Cómo aseguramos los secretos en pipelines de CI/CD?

Usa un gestor de secretos dedicado (HashiCorp Vault, AWS Secrets Manager, secretos de GitHub Actions). Nunca hardcodees secretos en archivos de pipeline ni variables de entorno. Usa OIDC para autenticación en la nube en lugar de claves estáticas. Rota los secretos trimestralmente y tras cualquier compromiso sospechado. Para runners self-hosted, asegúrate de que los secretos se limpian de los logs y que el runner es efímero.

¿Cuál es la diferencia entre SAST, DAST y SCA?

SAST (Static Application Security Testing) analiza el código fuente buscando vulnerabilidades sin ejecutarlo. DAST (Dynamic Application Security Testing) prueba una aplicación en ejecución desde fuera. SCA (Software Composition Analysis) escanea dependencias buscando vulnerabilidades conocidas. Los tres deberían correr en tu pipeline: SAST en cada PR, SCA en cada merge, DAST en despliegues a staging.

¿Deberíamos usar runners auto-gestionados o gestionados en la nube?

Los runners gestionados en la nube (GitHub-hosted, GitLab SaaS) son efímeros y aislados por defecto, lo que reduce la superficie de ataque. Los runners self-hosted son necesarios para acceso a red privada o hardware especializado, pero requieren endurecimiento: instancias efímeras, sin estado compartido entre jobs y segmentación de red entre build y producción. Nunca corras despliegues a producción en el mismo runner que builds de PRs no confiables.

¿Cómo implementamos doble aprobación para despliegues a producción?

Configura tu pipeline para requerir aprobación manual de dos miembros distintos del equipo antes de desplegar a producción. Usa reglas de protección de entornos en GitHub Actions o entornos protegidos de GitLab. Los aprobadores no deberían ser la misma persona que disparó el pipeline. Registra todas las aprobaciones con timestamp, usuario y razón para compliance de auditoría.

¿Qué es un SBOM y por qué lo necesitamos?

Un SBOM (Software Bill of Materials) es un inventario legible por máquina de todos los componentes de un artefacto de software, incluyendo dependencias transitivas, versiones y licencias. Habilita el escaneo de vulnerabilidades, compliance de licencias y transparencia de la cadena de suministro. Genera un SBOM para cada build usando herramientas como syft, trivy o el grafo de dependencias de GitHub. Almacena los SBOMs junto a los artefactos y reténlos durante la vida del software desplegado.

¿Qué es cosign y cómo funciona?

Cosign es una herramienta del proyecto Sigstore para firmar y verificar imágenes de contenedor y blobs. Usa firma sin claves (keyless) con tokens OIDC de tu proveedor de CI, eliminando la necesidad de gestionar claves de firma. La firma se almacena en un log de transparencia (Rekor), haciéndola verificable públicamente. Integra cosign en tu pipeline para firmar artefactos tras el build y verificar firmas antes del despliegue.

¿Cómo manejamos secretos para runners auto-gestionados?

Usa runners efímeros que se destruyen tras cada job. Inyecta secretos en runtime desde un gestor de secretos (Vault, AWS Secrets Manager). Nunca almacenes secretos en el disco del runner. Limpia los valores de secretos de los logs del pipeline usando enmascaramiento. Rota las credenciales del runner frecuentemente y audita los logs de acceso al runner. Para entornos sensibles, usa pools de runners dedicados por entorno con aislamiento de red.