Problema

Los pipelines de CI/CD son cada vez más atractivos para los atacantes porque, una vez dentro, pueden ejecutar código con los mismos privilegios que el propio runner. Un patrón recurrente es la inserción de workflow maliciosos que imitan a bots de CI (por ejemplo build-bot o auto-ci) y que roban secretos, credenciales de nube y tokens OIDC. Cuando el atacante controla un workflow que se dispara en cada push o mediante workflow_dispatch, puede exfiltrar datos en cada ejecución y, con un token OIDC válido, obtener acceso directo a los proveedores de nube sin necesidad de credenciales estáticas.

Este tipo de compromiso no depende de una vulnerabilidad específica del runner; se basa en permisos demasiado amplios y en la ausencia de revisiones de cambios en los archivos de workflow. Por eso, cualquier organización que permita que cualquier colaborador (incluidos bots) modifique .github/workflows/*.yml está expuesta a un vector de ataque que puede escalar rápidamente a cientos de repositorios.

Causa

  1. Permisos de escritura demasiado laxos

    • write o maintain en el repositorio permite crear o sobrescribir archivos de workflow.
    • Los equipos suelen confiar en que los bots internos son seguros y no aplican revisiones de código para cambios en .github/workflows.
  2. Falta de control de identidad en los actors

    • Los correos de los bots ([email protected]) son fáciles de falsificar.
    • GitHub permite que cualquier cuenta con permiso cree commits con cualquier autor/email.
  3. Uso implícito de OIDC sin restricciones

    • Los workflows pueden solicitar un token OIDC (id-token: write) y usarlo para autenticarse en AWS/GCP/Azure.
    • Si el workflow no está limitado a un environment o a un environment protection rule, el token es válido para cualquier recurso que confíe en la federación de GitHub.
  4. Ausencia de escaneo de secretos en el historial

    • Los atacantes insertan payloads codificados en Base64 dentro de los archivos de workflow.
    • Sin una política de escaneo retroactivo, esos cambios pasan desapercibidos.
  5. Desactivación de la revisión de workflow_dispatch

    • Los workflows que solo se ejecutan bajo workflow_dispatch pueden permanecer inactivos hasta que el atacante los active vía API, evitando detección temprana.

Solución

Una defensa en profundidad combina controles de permisos, revisión de cambios y limitaciones de OIDC. El objetivo es que cualquier modificación a un workflow pase por una revisión humana y que los tokens OIDC estén atados a entornos protegidos.

1. Restringir quién puede modificar workflows

  • Cambia el branch protection rule para requerir al menos una revisión aprobada antes de permitir push a main o a cualquier rama que contenga .github/workflows.
  • Usa la opción Require status checks to pass before merging y añade un secret scanning como check obligatorio.
  • Configura CODEOWNERS para que los archivos bajo .github/workflows/ tengan como propietarios a un equipo de seguridad.

2. Aplicar environment protection rules a los workflows que usan OIDC

  • Crea un environment llamado ci-prod y marca la opción Prevent all actions from accessing this environment without explicit approval.
  • En el workflow que necesita el token OIDC, especifica environment: ci-prod.
  • Habilita la aprobación manual o la política de deployment protection para que solo usuarios autorizados puedan ejecutar el workflow.

3. Limitar el alcance del token OIDC

  • Añade permissions: id-token: write solo cuando sea estrictamente necesario.
  • Usa audience: <your-cloud-provider> para que el token sea válido únicamente para el proveedor deseado.
  • En AWS, configura una IAM role con condición StringEquals sobre token.actions.githubusercontent.com:sub para que solo los repositorios y workflows específicos puedan asumirla.

4. Detectar y bloquear commits falsos de bots

  • Implementa una regla de commit signature verification (GPG) y exige que todos los commits en ramas protegidas estén firmados.
  • Usa GitHub Actions o un CI externo para buscar patrones de autor sospechosos (build-bot, auto-ci, pipeline-bot) y fallar la ejecución si se detectan.

5. Escaneo retroactivo de secretos y payloads

  • Ejecuta git log --all --grep='build-bot' --pretty=format:'%h %an %ae %s' para encontrar commits sospechosos.
  • Usa herramientas como trufflehog o gitleaks en el historial completo (--depth=0) para buscar cadenas codificadas en Base64 que puedan contener scripts.

6. Monitoreo de uso de OIDC y exfiltración de datos

  • Configura alertas en CloudTrail (AWS) o Activity Log (Azure) para detectar AssumeRoleWithWebIdentity provenientes de token.actions.githubusercontent.com.
  • En GitHub, habilita Security > Audit log y filtra eventos workflow_job.completed con conclusion: success y environment: ci-prod.

Cuándo aplicar esta solución

  • Síntomas: aparición de nuevos archivos .yml en .github/workflows sin PR, commits con autores de dominio noreply.dev, aumento inesperado de tráfico saliente desde runners.
  • Escenarios válidos: cualquier organización que use GitHub Actions para despliegues a la nube, especialmente si los workflows manejan credenciales o tokens OIDC.
  • Exclusiones: repositorios estrictamente internos que nunca exponen secretos y que usan runners auto‑hosted sin acceso a la red pública pueden reducir la superficie, pero aun así se recomienda aplicar al menos la revisión de code owners.

Código

# Buscar commits sospechosos por autor o email
git log --all --grep='build-bot' --grep='auto-ci' \
    --pretty=format:'%h %an %ae %s' > sospechosos.txt

# Escaneo retroactivo de secretos con trufflehog (instalar previamente)
trufflehog git file://$(pwd) --since-commit=HEAD --max-depth=0 \
    --regex --entropy=True > secret_findings.txt

Verificación

  1. Abre un pull request que modifique un workflow y verifica que el proceso de revisión obliga a al menos una aprobación del equipo de seguridad.
  2. Ejecuta gh api repos/:owner/:repo/actions/runs y confirma que los runs que usan environment: ci-prod aparecen con estado pending hasta que un aprobador los autorice.
  3. En la consola de tu proveedor de nube, revisa los logs de AssumeRoleWithWebIdentity. Cada entrada debe contener sub: repo:<owner>/<repo>:ref:refs/heads/main. Si aparecen valores desconocidos, investiga el workflow correspondiente.
  4. Revisa que git log ya no muestre commits con autores falsificados después de aplicar la política de firmas GPG.

Notas adicionales

  • La firma GPG no impide que un atacante cree un commit con un autor falsificado, pero sí garantiza que el hash del commit proviene de una clave conocida.
  • Los runners auto‑hosted pueden ser aislados con VPCs y políticas de salida restrictivas; sin embargo, el token OIDC sigue siendo válido si el workflow logra ejecutarse.
  • Mantener una lista de approved actions (usando actions/checkout@v3 y versiones con hash SHA) reduce la superficie de ataque por acciones de terceros.
  • La rotación de credenciales estática sigue siendo buena práctica, pero sin controlar los tokens OIDC la rotación no corta la cadena de exfiltración.
  • Finalmente, documenta el proceso de auditoría y compártelo con todos los equipos de desarrollo; la cultura de revisión de workflows es la primera línea de defensa.