Preámbulo
En 2025 y 2026, observamos un patrón que se desarrollaba en toda la industria. Los atacantes dejaron de atacar directamente los servidores de producción y empezaron a atacar la automatización que se despliega en ellos. Credenciales de desarrollador comprometidas, un archivo de flujo de trabajo modificado y, de repente, todos los secretos en un entorno CI/CD se transmiten a un punto final controlado por el atacante. Vimos esto en incidentes que involucraron grandes proyectos de código abierto, compañías de Fortune 500 y herramientas de infraestructura crítica.
La cadena de ataques es engañosamente simple:
Credenciales de desarrollador robadas → archivo de flujo de trabajo modificado → secretos de CI recolectados → Movimiento lateral a la nube y producción
Hoy en día estamos abriendo el código de código cicd-abuse-detector, una plantilla de CI directa que emplea extracción de señales basadas en regex y análisis LLM para detectar cambios sospechosos en las canalizaciones CI/CD. Funciona en GitHub Actions, GitLab CI y Azure DevOps, y está diseñado en torno a las técnicas de ataque reales documentadas en la investigación de seguridad pública.
Conclusiones clave
- Los entornos CI/CD son objetivos de alto valor porque un único flujo de trabajo comprometido puede extraer credenciales en la nube, tokens de registro de empaquetados, claves de firma de código, claves de despliegue y tokens OIDC simultáneamente
- La herramienta extrae 50+ señales regex y metadatos de diferenciales, y luego las pasa con el diferencial completo a Claude para un análisis estructurado de amenazas. Sin Python, sin dependencias más allá de bash y la línea de comando Claude Code
- Se probaron patrones de detección contra kits de herramientas ofensivos como Nord Stream y Gato-X, y contra incidentes reales como ArtiPACKED y HackerBot-Claw
- El proyecto incluye 19 diferenciales maliciosos y cuatro diferenciales de ejemplo benignos modelados a partir de incidentes específicos, y un conjunto de pruebas automatizado que valida cada señal
Por qué las tuberías CI/CD son un objetivo principal
Si dedicas tiempo a revisar GitHub Actions o configuraciones de GitLab CI, puede que notes cuánta confianza se concentra en estos archivos. Un flujo de trabajo típico de despliegue tiene acceso a credenciales AWS, tokens de publicación npm, contraseñas de Docker Hub y un token de GitHub con licencias de escritura, todo al mismo tiempo. La superficie de ataque no es un servidor con un CVE, es un archivo YAML.
Recolección de credenciales a gran escala
Un atacante con credenciales de desarrollador robadas modifica un flujo de trabajo para exfiltrar secretos disponibles en el entorno de CI. La campaña GhostAction en septiembre de 2025 demostró esto a gran escala, comprometiendo 327 usuarios de GitHub en 817 repositorios. Se robaron 3.325 secretos mediante archivos de flujo de trabajo inyectados que enviaban credenciales POST a los endpoints atacantes.
El gusano npm Shai-Hulud fue más allá. Este ataque autopropagante recolectaba GitHub Personal Access Tokens mediante token gh auth, ejecutaba TruffleHog para reconocimiento secreto y empleaba tokens comprometidos para inyectar silenciosamente código malicioso en otros paquetes propiedad del mismo desarrollador. Solo en la primera oleada se publicaron más de 46.000 paquetes maliciosos.
Explotación de disparadores privilegiados
El disparador pull_request_target es una de las características más peligrosas de GitHub Actions. A diferencia de un disparador pull_request normal, ejecuta flujos de trabajo en el contexto del repositorio base con acceso a secretos, pero puede ejecutar código desde un fork no confiable. La investigación de Orca "Pull Request Nightmare" demostró esto frente a repositorios mantenidos por Google, Microsoft y NVIDIA.
En febrero de 2026, una campaña automatizada llamada HackerBot-Claw escaneó sistemáticamente los repositorios públicos en busca de esta configuración exacta. Empleaba cinco técnicas diferentes de explotación, incluyendo funciones de Go envenenadas de init() , inyección de comandos de nombre de salto, inyección basada en nombres de archivo, inyección directa de scripts e inyección de prompts de IA contra revisores de código basados en Claude. En el caso más grave, el repositorio Trivy de Aqua Security fue completamente comprometido, lo que llevó a un ataque a la cadena de suministro aguas abajo que expuso 33.000 secretos en casi 7.000 máquinas. Según se documentó, este ataque a la cadena de suministro fue posible gracias a tokens comprometidos que eran válidos semanas luego de ser robados inicialmente.
El resto de la taxonomía
Más allá de la obtención de credenciales y la explotación de desencadenantes, el modelo de amenazas abarca cuatro categorías adicionales que aparecen de forma constante en la investigación pública:
- Escalada de licencias, donde agregar licencias: write-all o id-token: write amplía el radio de explosión de cualquier compromiso
- Segmentación de runners, redirigir trabajos a runners autoalojados que a menudo tienen acceso a la red a la infraestructura interna, o especificar imágenes de contenedores controladas por atacantes
- Manipulación de la cadena de suministro mediante referencias de acciones mutables (usando versiones @main en lugar de SHA), ejecución remota de scripts (
curl|bash), intercambios de registros de archivos de bloqueo y envenenamiento de dependencias - Evasión de defensa mediante manipulación de la marca de tiempo de compromiso, haciendo que los archivos maliciosos parezcan antiguos y de confianza. KL4R10N documentado esta técnica en campañas vinculadas a la RPDC donde retrocede la infraestructura de referencia de commits que no existía en la fecha declarada
Cada uno de estos se corresponde con técnicas específicas de MITRE ATT& CK: T1552 (Credenciales no seguras), T1195 (Compromiso de la cadena de suministro), T1070.006 (Timestomp) y T1059 (Intérprete de comandos y scripts).
Cómo funciona el detector
Queríamos que las plantillas funcionaran sin necesidad de Python, runtimes personalizados ni dependencias complejas. Todo se ejecuta en utilidades estándar de shell en un runner ubuntu-latest por defecto, y la única herramienta instalada es la Claude Code CLI vía npm, que gestiona autenticación, retries y enrutamiento de modelos.
Fase 1: Filtro y diferenciales
Cuando se abre una solicitud pull (o un push llega a una rama protegida), el flujo de trabajo identifica los archivos modificados a través de tres niveles de rutas relevantes para CI/CD. El primer nivel cubre archivos de CI núcleo como definiciones de flujos de trabajo, configuraciones de pipelines y Makefiles. La segunda abarca artefactos de construcción y liberación como Dockerfiles, manifiestos de paquetes, archivos de bloqueo y scripts de firma o despliegue. El tercer nivel recoge configuraciones de entorno de desarrollo como .vscode/tasks.json y .devcontainer archivos.
Cada archivo se diferencia individualmente y tiene un límite de 10.000 caracteres. Hacemos esto por archivo en lugar de globalmente porque un único límite en el diferencial combinado es un vector de bypass. Un atacante puede rellenar un cambio malicioso en el flujo de trabajo con una gran edición benigna de Dockerfile para llevar el exploit más allá del límite de caracteres.
Etapa 2: Extracción de señales
Antes de que el LLM detecte nada, los patrones regex 50+ escanean cada diferencial en busca de patrones conocidos como peligrosos. Estas señales son de advertencia. Nunca bloquean el análisis, pero proporcionan al LLM un resumen de amenazas preseleccionado. Algunos ejemplos:
| Señal | Patrón | Lo que atrapa |
|---|---|---|
secrets_context | ${{.*secrets. | Interpolación secreta directa en flujos de trabajo |
pull_request_target | pull_request_target | El disparador peligroso que otorga secretos al código de relaciones públicas |
checkout_ref | ref:.*github.event.pull_request.head.(sha|ref) | Código PR no confiable verificado en un contexto privilegiado |
double_base64 | base64.*|.*base64 | Doble codificación para evadir el enmascaramiento de logarítmicas (técnica Nord Stream) |
ld_preload | LD_PRELOAD | Ejecución arbitraria de código mediante inyección de variables de entorno |
vscode_auto_task | runOn.*folderOpen | Tarea de VS Code que se ejecuta al abrir una carpeta (Entrevista Contagiosa) |
La lista de señales se basa en herramientas adversariales reales, incluyendo Nord Stream y Gato-X, y se prueba contra diferenciales de ejemplo maliciosos 19 modelados a partir de incidentes específicos.
El detector funciona de forma idéntica en GitHub Actions, GitLab CI y Azure DevOps. Aquí tienes las detecciones disparando en cada plataforma:
Fase 3: Análisis de LLM
El resumen de la señal, el diferencial completo, el perfil del autor y los metadatos de commit se agrupan y envían a Claude a través de la CLI de código de Claude. El prompt de análisis guía al modelo por varias áreas:
- Comprensión diferencial y evaluación de riesgos por expediente
- Interpretación de señales con contexto (una señal por sí sola no es un veredicto)
- Análisis temporal para commits retroactivos
- Evaluación del fideicomiso de autores empleando la antigüedad de la cuenta, historial de contribuciones y membresía en la organización
- Calibración de severidad frente a una tabla de combinación de señales con 60+ entradas
- El reconocimiento de falsos positivos (por ejemplo, cURL para descargar herramientas conocidas no es exfiltración)
- Recomendaciones concretas y accionables ("Fijar acciones/node@main de configuración a un SHA específico" en lugar de "revisar cuidadosamente")
El resultado es un veredicto JSON estructurado que contiene gravedad, confianza, razonamiento, pruebas y recomendaciones, todo validado frente a un Esquema JSON.
Fase 4: Alerta y puerta
Según la gravedad del veredicto, el flujo de trabajo publica un resumen de pasos, crea un problema, envía una notificación en Slack y, opcionalmente, falla la comprobación de PR si la gravedad alcanza un umbral configurado.
Las alertas en Slack y GitHub Issues resuelven el problema de notificaciones inmediatas, pero no te dan un historial consultable. Cada veredicto que produce el detector (por ejemplo, benigno, sospechoso o malicioso), pueden enviar opcionalmente a Elasticsearch como un documento estructurado en los logs-cicd.abuse-default flujo de datos. El flujo de trabajo agrupa el veredicto junto con los metadatos CI/CD (plataforma, repositorio, actor, tipo de evento, URL de ejecución) en un único índice que abarca las tres plataformas soportadas.
Aquí es donde la correlación entre plataformas se vuelve práctica. Una alerta de Acciones de GitHub y una alerta de CI de GitLab del mismo actor aterrizan en el mismo flujo de datos, consultables en un solo ES|Declaración QL:
FROM logs-cicd.abuse-*
WHERE verdict.verdict IN ("malicious", "suspicious") AND @timestamp > NOW() - 7 days
EVAL platform = cicd.platform, repo = cicd.repository, actor = cicd.actor, severity = verdict.severity
KEEP @timestamp, platform, repo, actor, severity
SORT @timestamp DESC
El esquema incluye cicd.platform, cicd.repository, CICD.Actor y el objeto completo del veredicto (veredicto, gravedad, confianza, resumen, razones, pruebas), facilitando la elaboración de reglas de detección. Una campaña coordinada que afecta a varios repositorios en una hora, un reincidente marcado en varias plataformas, o un pico de hallazgos críticos que justifique una página de respuesta a incidentes pueden correlacionar.
Validación contra ataques reales
Para validar la cobertura, comparamos nuestros patrones de detección con el código fuente real de herramientas ofensivas, investigaciones publicadas y autopsias públicas.
Nord Stream: coincidencia literal de cargas útiles
Nord Stream es la herramienta de extracción de secretos CI/CD de código abierto de Synacktiv, que soporta GitHub, GitLab y Azure DevOps. Extrajimos la fuente del generador YAML (nordstream/yaml/github.py) y comparamos sus plantillas de salida con nuestros diferenciales de ejemplo.
- La plantilla de payload de GitHub emplea
env -0 | awk -v RS='0' '/^secret_/ {print $0}' | base64 -w0 | base64 -w0. Nuestronord-stream-pipeline-exfil.diffcontiene esta línea literalmente, y nuestras señalesdouble_base64,env_null_dumpyenv_secret_grepdisparan. - La plantilla OIDC de Azure emplea
azure/login@v1con licenciasid-token: writeseguidos deget-access-token | base64 -w0 | base64 -w0cuenta de az. Nuestro diferencial captura exactamente este flujo y activacloud_auth_actionyid_token_write. - Las técnicas de la tubería Azure DevOps (
addSpnToEnvironmentpara exposición a credenciales SPN,DownloadSecureFilepara robo de archivos seguros, parcheo de código de tareas SSH mediante modificaciónssh.js) están todas presentes ennord-stream-azure-devops.diffy detectadas por señales específicas de la plataforma.
ArtiPACKED: la condición de la raza de artefactos
La investigación de ArtiPACKED de la Unidad de Palo Alto 42 mostró que subir todo el directorio de préstamo como artefacto filtra el archivo .git/config que contiene el GITHUB_TOKEN. Con la API de artefactos v4 permitiendo descargas a mitad de ejecución, un atacante puede extraer y usar el token antes de que el trabajo se complete.
Nuestro artifact-token-leak.diff modela exactamente este patrón, usando upload-artifact con path: . (todo el espacio de trabajo). La señal de upload_artifact la detecta y el LLM evalúa si el alcance de subida incluye el directorio .git .
GITHUB_ENV inyección: LD_PRELOAD a RCE
La investigación de Legit Security sobre Google Firebase y Apache mostró que escribir entradas no confiables en $GITHUB_ENV permite a un atacante establecer variables arbitrarias de entorno como LD_PRELOAD y NODE_OPTIONS, logrando la ejecución de código en flujos de trabajo privilegiados.
Nuestro github-env-injection.diff reproduce esta técnica con tres cargas útiles distintas, incluyendo LD_PRELOAD apuntando a un objeto compartido malicioso, NODE_OPTIONS con una inyección requerida y manipulación deGITHUB_PATH dólares. Las señales de github_env_write, ld_preloady github_path_write se activan como se esperaba.
Entrevista contagiosa: configuración del IDE como acceso inicial
La campaña Entrevistas Contagiosas , atribuida a la RPDC, se dirige a los desarrolladores mediante entrevistas de trabajo falsas, distribuyendo repositorios con archivos de .vscode/tasks.json que se ejecutan automáticamente al abrir carpetas. La presentación está oculta (reveal: never, echo: false), y la carga útil emplea curl | node para la ejecución silenciosa.
Nuestro ide-config-poisoning.diff captura toda la cadena de ataques, incluyendo el disparador de auto-ejecución (runOn: folderOpen), la presentación oculta, la carga útil de curl | node , la entrada de files.exclude que oculta el directorio .vscode y un gancho de postinstalación trojanizado con URLs codificadas en base64 y eval() para la ejecución de código. Seis señales captan esto a la vez.
Recomendaciones defensivas
Más allá de desplegar el detector, aquí hay algunas medidas de endurecimiento que surgieron directamente de los patrones de ataque que estudiamos:
- Fija todas las acciones a SHA, no etiquetas, ni ramas. Las referencias fijadas por SHA evitan ataques retroactivos de modificación de etiquetas como
tj-actions(CVE-2025-30066). - Secretos de alcance para pasos individuales en lugar de usar variables de entorno a nivel de trabajo. Cada paso solo debería tener acceso a los secretos que realmente necesita.
- Emplea fichas efímeras y de corta duración cuando sea posible para reducir la superficie de ataque
- Evita
pull_request_targetsalvo que sea estrictamente necesario. Si tienes que usarla, nunca revises el código de la cabeza de PR en el mismo flujo de trabajo. Emplea unworkflow_run-triggered workflowseparado para operaciones que requieran tanto secretos como contexto de PR. - Establece licencias explícitas en cada flujo de trabajo porque las licencias predeterminadas de los tokens son demasiado amplios. Establece
permissions: {}a nivel de flujo de trabajo y agrega licencias específicas por trabajo. - Activa
persist-credentials: falseal finalizar ya que el comportamiento predeterminado de acciones/checkout persiste en elGITHUB_TOKENen el directorio de.git. Si subes artefactos, este token va con ellos.
Resumen
Las tuberías CI/CD se convirtieron en una superficie de ataque importante para el compromiso de la cadena de suministro. La misma automatización que hace posible la entrega moderna de software es la que los atacantes explotan para obtener credenciales, envenenar paquetes y cambiar a infraestructura en la nube. La revisión de código tradicional no capta bien estos patrones porque son sutiles, específicos de la plataforma y diseñados para parecer cambios legítimos de DevOps.
Combinar la extracción de señales basada en regex con el razonamiento LLM nos permite mostrar estos patrones en la fase de pull request, antes de que lleguen a producción. El repositorio incluye el modelo completo de amenazas, el conjunto de pruebas y diferenciales de ejemplo si quieres profundizar en los detalles o adaptarlo a tu propio entorno.
Para empezar, consulta el repositorio cicd-abuse-detector para instrucciones de configuración, el modelo completo de amenazas y diferenciales de ejemplo. Siempre nos interesa conocer nuevos patrones de ataque e ideas de detección. Chatea con nosotros en nuestra comunidad Slack y haz preguntas en nuestros foros de discusión.
Abuso de CI/CD a través de MITRE ATT&CK
Empleamos el marco MITRE ATT&CK para mapear las tácticas, técnicas y procedimientos que los adversarios emplean contra las canalizaciones CI/CD.
Táctica
| Táctica | Relevancia CI/CD |
|---|---|
| Acceso a credenciales (TA0006) | Recolectando secretos de entornos CI |
| Ejecución (TA0002) | Ejecución de comandos en pipeline runners |
| Persistencia (TA0003) | Disparadores programados, flujos de trabajo basados en crons |
| Evasión de Defensa (TA0005) | Manipulación de marca de tiempo de compromiso, evasión de enmascaramiento de registro |
| Acceso inicial (TA0001) | Credenciales de desarrollador comprometidas, phishing por PATs |
| Movimiento lateral (TA0008) | Uso de credenciales de la nube recolectadas para pivotar |
Técnicas
| Técnica | Aplicación CI/CD |
|---|---|
| T1552: Credenciales no aseguradas | Secretos expuestos en variables de entorno CI, artefactos y memoria del runner |
| T1195.002: Cadena de suministro de software de compromiso | Acciones, dependencias y archivos de bloqueo envenenados |
| T1059: Intérprete de comandos y secuencias de comandos | curl |
| T1070.006: Timestomp | Fechas de commit retroactivas para evitar la revisión |
| T1098: Manipulación de cuentas | Escalada de licencias mediante write-all, id-token: write |
| T1078: Cuentas válidas | PATs robados por desarrolladores usados para modificar flujos de trabajo |
Referencias
A lo largo de la investigación anterior se hizo referencia a lo siguiente:
- https://github.com/elastic/cicd-abuse-detector
- https://github.com/synacktiv/nord-stream
- https://github.com/adnanekhan/gato-x
- https://unit42.paloaltonetworks.com/github-repo-artifacts-leak-tokens/
- https://blog.gitguardian.com/ghostaction-campaign-3-325-secrets-stolen
- https://www.reversinglabs.com/blog/shai-hulud-worm-npm
- https://orca.security/resources/blog/pull-request-nightmare-github-actions-rce/
- https://orca.security/resources/blog/hackerbot-claw-github-actions-attack/
- https://www.stepsecurity.io/blog/hackerbot-claw-github-actions-exploitation
- https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0
- https://www.abstract.security/blog/contagious-interview-tracking-the-vs-code-tasks-infection-vector
- https://about.codecov.io/apr-2021-post-mortem/
- https://kl4r10n.tech/blog/when-git-history-lies
- https://www.synacktiv.com/en/publications/github-actions-exploitation-dependabot
- https://docs.anthropic.com/en/docs/claude-code
Acerca de Elastic Security Labs
Elastic Security Labs es la rama de inteligencia de amenazas de Elastic Security dedicada a crear cambios positivos en el panorama de amenazas. Elastic Security Labs proporciona investigación disponible públicamente sobre amenazas emergentes con un análisis de los objetivos estratégicos, operativos y tácticos del adversario, y luego integra esa investigación con las capacidades de detección y respuesta integradas de Elastic Security.
Sigue a Elastic Security Labs en Twitter @elasticseclabs y echa un vistazo a nuestra investigación en www.elastic.co/security-labs/.