Preâmbulo
Em 2025 e 2026, observamos um padrão se repetir em todo o setor. Os atacantes deixaram de visar diretamente os servidores de produção e começaram a atacar a automação que realiza as implantações neles. Credenciais de desenvolvedor comprometidas, um arquivo de fluxo de trabalho modificado e, de repente, todos os segredos em um ambiente CI/CD estão sendo transmitidos para um endpoint controlado pelo invasor. Vimos isso acontecer em incidentes envolvendo grandes projetos de código aberto, empresas da Fortune 500 e ferramentas de infraestrutura crítica.
A cadeia de ataque é enganosamente simples:
Credenciais de desenvolvedor roubadas → Arquivo de fluxo de trabalho modificado → Segredos de CI coletados → Movimentação lateral para a nuvem e produção
Hoje estamos disponibilizando o código aberto do cicd-abuse-detector, um modelo de CI pronto para uso que utiliza extração de sinais baseada em expressões regulares e análise LLM para detectar alterações suspeitas em pipelines de CI/CD. Ele funciona com o GitHub Actions, GitLab CI e Azure DevOps, e foi projetado com base em técnicas de ataque do mundo real documentadas em pesquisas públicas de segurança.
Principais conclusões
- Os ambientes de CI/CD são alvos de alto valor porque um único fluxo de trabalho comprometido pode exfiltrar credenciais de nuvem, tokens de registro de pacotes, chaves de assinatura de código, chaves de implantação e tokens OIDC simultaneamente.
- A ferramenta extrai mais de 50 sinais de expressões regulares e metadados das diferenças entre os arquivos, e os envia, juntamente com a diferença completa, para o Claude para análise estruturada de ameaças. Sem Python, sem dependências além do bash e da CLI do Claude Code
- Os padrões de detecção foram testados contra ferramentas ofensivas como Nord Stream e Gato-X, e contra incidentes reais, incluindo ArtiPACKED e HackerBot-Claw.
- O projeto é fornecido com 19 exemplos de diferenças maliciosas e quatro benignas, modeladas a partir de incidentes específicos, e um conjunto de testes automatizados que valida cada sinal.
Por que os pipelines de CI/CD são um alvo prioritário
Se você dedicar tempo a revisar as configurações do GitHub Actions ou do GitLab CI, poderá perceber quanta confiança está concentrada nesses arquivos. Um fluxo de trabalho de implantação típico tem acesso simultâneo a credenciais da AWS, tokens de publicação do npm, senhas do Docker Hub e um token do GitHub com permissões de gravação. A superfície de ataque não é um servidor com uma CVE, mas sim um arquivo YAML.
Coleta de credenciais em larga escala
Um atacante com credenciais de desenvolvedor roubadas modifica um fluxo de trabalho para exfiltrar segredos disponíveis no ambiente de CI (Integração Contínua). A campanha GhostAction em setembro 2025 demonstrou isso em grande escala, comprometendo 327 usuários do GitHub em 817 repositórios. 3.325 segredos foram roubados por meio de arquivos de fluxo de trabalho injetados que enviavam credenciais via POST para os endpoints do atacante.
O worm npm Shai-Hulud foi além. Este ataque autopropagável coletou tokens de acesso pessoal do GitHub por meio do token de autenticação gh, executou o TruffleHog para reconhecimento secreto e usou os tokens comprometidos para injetar silenciosamente código malicioso em outros pacotes pertencentes ao mesmo desenvolvedor. Mais de 46.000 pacotes maliciosos foram publicados somente na primeira onda.
Exploração de gatilhos privilegiados
O gatilho `pull_request_target` é um dos recursos mais perigosos do GitHub Actions. Diferentemente de um gatilho pull_request comum, ele executa fluxos de trabalho no contexto do repositório base com acesso a segredos, mas pode executar código de um fork não confiável. A pesquisa "Pull Request Nightmare" da Orca demonstrou isso em repositórios mantidos pelo Google, Microsoft e NVIDIA.
Em fevereiro de 2026, uma campanha automatizada chamada HackerBot-Claw fez uma varredura sistemática em repositórios públicos em busca dessa configuração incorreta específica. Ele usou cinco técnicas de exploração diferentes, incluindo funções Go envenenadas init() , injeção de comando de nome de ramificação, injeção baseada em nome de arquivo, injeção direta de script e injeção de prompt de IA contra revisores de código baseados em Claude. No caso mais grave, o repositório Trivy da Aqua Security foi totalmente comprometido, levando a um ataque subsequente na cadeia de suprimentos que expôs 33.000 segredos em quase 7.000 máquinas. Conforme documentado, esse ataque à cadeia de suprimentos foi possível graças a tokens comprometidos que permaneceram válidos semanas após o roubo inicial.
O restante da taxonomia
Além da coleta de credenciais e da exploração de vulnerabilidades, o modelo de ameaças abrange quatro categorias adicionais que aparecem consistentemente em pesquisas públicas:
- A escalada de permissões, onde a adição de permissões como `write-all` ou `id-token: write`, amplia o alcance de qualquer comprometimento.
- O direcionamento de executores, o redirecionamento de tarefas para executores auto-hospedados que frequentemente têm acesso à rede da infraestrutura interna ou a especificação de imagens de contêiner controladas pelo atacante, são exemplos de técnicas utilizadas.
- Manipulação da cadeia de suprimentos por meio de referências de ação mutáveis (usando @main em vez de versões fixadas por SHA), execução remota de scripts (
curl|bash), trocas de registro de arquivos de bloqueio e envenenamento de dependências - Evasão de defesa por meio da manipulação do carimbo de data/hora de commit, fazendo com que arquivos maliciosos pareçam antigos e confiáveis. KL4R10N documentou essa técnica em campanhas ligadas à Coreia do Norte, onde commits retroativos faziam referência a infraestrutura que não existia na data alegada.
Cada um desses mapeamentos corresponde a técnicas específicas do MITRE ATT&CK : T1552 (Credenciais não seguras), T1195 (Comprometimento da cadeia de suprimentos), T1070.006 (Timestomp) e T1059 (Interpretador de comandos e scripts).
Como funciona o detector
Queríamos que os modelos funcionassem sem exigir Python, ambientes de execução personalizados ou dependências complexas. Tudo é executado em utilitários de shell padrão em um ambiente ubuntu-latest padrão, e a única ferramenta instalada é a CLI do Claude Code via npm, que lida com autenticação, novas tentativas e roteamento de modelos.
Etapa 1: Filtrar e diferenciar
Quando uma solicitação de pull request é aberta (ou um push é aplicado a um branch protegido), o fluxo de trabalho identifica os arquivos alterados em três níveis de caminhos relevantes para CI/CD. O primeiro nível abrange arquivos essenciais de CI, como definições de fluxo de trabalho, configurações de pipeline e Makefiles. A segunda parte abrange artefatos de compilação e lançamento, como Dockerfiles, manifestos de pacotes, arquivos de bloqueio e scripts de assinatura ou implantação. O terceiro nível coleta configurações do ambiente de desenvolvimento, como .vscode/tasks.json e .devcontainer. arquivos.
Cada arquivo é comparado individualmente e limitado a 10.000 caracteres. Fazemos isso por arquivo, em vez de globalmente, porque uma única alteração na diferença combinada é um vetor de bypass. Um atacante pode complementar uma alteração maliciosa no fluxo de trabalho com uma grande edição benigna em um Dockerfile para que a exploração ultrapasse o limite de caracteres.
Etapa 2: Extração de sinal
Antes que o LLM veja qualquer coisa, mais de 50 padrões de expressões regulares examinam cada diferença em busca de padrões perigosos conhecidos. Esses sinais são meramente indicativos. Eles nunca restringem a análise, mas fornecem ao LLM um resumo de ameaças pré-selecionado. Alguns exemplos:
| Sinal | Padrão | O que ele captura |
|---|---|---|
secrets_context | ${{.*secrets. | Interpolação secreta direta em fluxos de trabalho |
pull_request_target | pull_request_target | O gatilho perigoso que concede segredos ao código PR |
checkout_ref | ref:.*github.event.pull_request.head.(sha|ref) | Código PR não confiável verificado em um contexto privilegiado |
double_base64 | base64.*|.*base64 | Codificação dupla para evitar mascaramento de logs (técnica Nord Stream) |
ld_preload | LD_PRELOAD | Execução de código arbitrário por meio de injeção de variáveis de ambiente |
vscode_auto_task | runOn.*folderOpen | Tarefa do VS Code que é executada ao abrir uma pasta (Entrevista Contagious) |
A lista de sinais é baseada em ferramentas adversárias reais, incluindo Nord Stream e Gato-X, e testada em relação a 19 exemplos de diferenças maliciosas modeladas a partir de incidentes específicos.
O detector funciona de forma idêntica no GitHub Actions, GitLab CI e Azure DevOps. Aqui estão as detecções disparadas em cada plataforma:
Etapa 3: Análise LLM
O resumo do sinal, o diff completo, o perfil do autor e os metadados do commit são agrupados e enviados para Claude por meio da CLI do Claude Code. O comando de análise guia o modelo por diversas áreas:
- Compreensão diferencial e avaliação de risco por arquivo
- Interpretação de sinais com contexto (um sinal por si só não constitui um veredicto)
- Análise temporal para commits retroativos
- Avaliação da confiança do autor com base na idade da conta, histórico de contribuições e participação na organização.
- Calibração de severidade em relação a uma tabela de combinação de sinais com mais de 60 entradas.
- Reconhecimento de falso positivo (por exemplo, o uso do cURL para baixar ferramentas conhecidas não é exfiltração).
- Recomendações concretas e práticas ("Fixar actions/setup-node@main a um SHA específico" em vez de "revisar cuidadosamente")
O resultado é um veredicto JSON estruturado contendo gravidade, confiança, justificativa, evidências e recomendações, todos validados em relação a um esquema JSON.
Etapa 4: Alerta e portão
Com base na gravidade do veredicto, o fluxo de trabalho publica um resumo das etapas, cria um problema, envia uma notificação no Slack e, opcionalmente, reprova a verificação do PR se a gravidade atingir um limite configurado.
Os alertas no Slack e os problemas do GitHub resolvem o problema da notificação imediata, mas não fornecem um histórico que possa ser consultado. Cada veredicto produzido pelo detector (por exemplo) benignos, suspeitos ou maliciosos), podem opcionalmente ser enviados para o Elasticsearch como um documento estruturado no arquivo logs-cicd.abuse-default. fluxo de dados. O fluxo de trabalho envia o veredicto juntamente com metadados de CI/CD (plataforma, repositório, ator, tipo de evento, URL de execução) para um único índice que abrange todas as três plataformas suportadas.
É aqui que a correlação entre plataformas se torna prática. Um alerta do GitHub Actions e um alerta do GitLab CI do mesmo agente chegam ao mesmo fluxo de dados, podendo ser consultados em uma única instrução ES|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
O esquema inclui cicd.platform, repositório cicd, O cicd.actor e o objeto de veredicto completo (veredicto, gravidade, confiança, resumo, razões, evidências) tornam simples a criação de regras de detecção. Uma campanha coordenada que atinge vários repositórios em uma hora, um infrator reincidente sinalizado em diversas plataformas ou um pico de descobertas críticas que justifica uma página de resposta a incidentes podem ser correlacionados.
Validação contra ataques reais
Para validar a abrangência, comparamos nossos padrões de detecção com o código-fonte real de ferramentas ofensivas, pesquisas publicadas e análises pós-ataque públicas.
Nord Stream: correspondência exata de carga útil
O Nord Stream é a ferramenta de extração de segredos CI/CD de código aberto da Synacktiv, compatível com GitHub, GitLab e Azure DevOps. Extraímos o código-fonte do gerador YAML (nordstream/yaml/github.py) e comparamos seus modelos de saída com nossos diffs de exemplo.
- O modelo de payload do GitHub usa
env -0 | awk -v RS='0' '/^secret_/ {print $0}' | base64 -w0 | base64 -w0. Nossonord-stream-pipeline-exfil.diffcontém esta linha literalmente, e nossosdouble_base64,env_null_dumpeenv_secret_grepsinalizam todos os fogos. - O modelo OIDC do Azure usa
azure/login@v1com permissõesid-token: writeseguido pela conta azget-access-token | base64 -w0 | base64 -w0. Nossa diferença captura esse fluxo exato e acionacloud_auth_actioneid_token_write. - As técnicas de pipeline do Azure DevOps (
addSpnToEnvironmentpara exposição de credenciais SPN,DownloadSecureFilepara roubo seguro de arquivos, patch de origem de tarefa SSH via modificação dessh.js) estão todas presentes emnord-stream-azure-devops.diffe detectadas por sinais específicos da plataforma.
ArtiPACKED: a condição de corrida do artefato
A pesquisa ArtiPACKED da Palo Alto Unit 42 mostrou que o upload de todo o diretório de checkout como um artefato vaza o arquivo .git/config que contém o GITHUB_TOKEN. Com a API de artefatos v4 permitindo downloads durante a execução, um invasor pode extrair e usar o token antes que a tarefa seja concluída.
Nosso modelo artifact-token-leak.diff segue exatamente esse padrão, usando upload-artifact com path: . (todo o espaço de trabalho). O sinal upload_artifact o captura e o LLM avalia se o escopo de upload inclui o diretório .git .
Injeção de GITHUB_ENV: LD_PRELOAD para RCE
A pesquisa da Legit Security sobre o Google Firebase e o Apache mostrou que escrever entradas não confiáveis para $GITHUB_ENV permite que um invasor defina variáveis de ambiente arbitrárias como LD_PRELOAD e NODE_OPTIONS, conseguindo executar código em fluxos de trabalho privilegiados.
Nosso github-env-injection.diff reproduz essa técnica com três payloads distintos, incluindo LD_PRELOAD apontando para um objeto compartilhado malicioso, NODE_OPTIONS com uma injeção necessária e $GITHUB_PATH manipulação. Os sinais github_env_write, ld_preload e github_path_write são todos disparados conforme o esperado.
Entrevista Contagiosa: Configuração da IDE como acesso inicial
A campanha Contagious Interview, atribuída à Coreia do Norte, visa desenvolvedores por meio de falsas entrevistas de emprego, distribuindo repositórios com arquivos .vscode/tasks.json que são executados automaticamente ao abrir a pasta. A apresentação está oculta (reveal: never, echo: false), e a carga útil usa curl | node para execução silenciosa.
Nosso ide-config-poisoning.diff captura toda a cadeia de ataque, incluindo o gatilho de execução automática (runOn: folderOpen), a apresentação oculta, a carga útil curl | node , a entrada files.exclude que oculta o diretório .vscode e um gancho de pós-instalação trojanizado com URLs codificados em base64 e eval() para execução de código. Seis sinais captam isso simultaneamente.
Recomendações de defesa
Além da implementação do detector, aqui estão algumas medidas de segurança que surgiram diretamente dos padrões de ataque que estudamos:
- Vincule todas as ações ao SHA, não às tags, nem aos branches. Referências fixadas por SHA impedem ataques de modificação retroativa de tags como
tj-actions(CVE-2025-30066). - Limite os segredos a etapas individuais em vez de usar variáveis de ambiente no nível do trabalho. Cada etapa deve ter acesso apenas aos segredos de que realmente precisa.
- Utilize tokens efêmeros e de curta duração sempre que possível para reduzir a superfície de ataque.
- Evite
pull_request_targeta menos que seja estritamente necessário. Se você precisar usá-lo, nunca faça o checkout do código principal do PR no mesmo fluxo de trabalho. Use umworkflow_run-triggered workflowseparado para operações que precisam de segredos e contexto PR. - Defina permissões explícitas em cada fluxo de trabalho, pois as permissões padrão do token são muito abrangentes. Defina
permissions: {}no nível do fluxo de trabalho e adicione permissões específicas por tarefa. - Habilite
persist-credentials: falseno checkout, pois o comportamento padrão de actions/checkout persiste oGITHUB_TOKENno diretório.git. Se você enviar artefatos, este token será enviado junto com eles.
Resumo
Os pipelines de CI/CD tornaram-se uma importante superfície de ataque para comprometimento da cadeia de suprimentos. A mesma automação que torna possível a entrega de software moderno é o que os atacantes exploram para coletar credenciais, envenenar pacotes e atacar a infraestrutura em nuvem. A revisão de código tradicional não detecta bem esses padrões porque eles são sutis, específicos da plataforma e projetados para parecerem alterações legítimas de DevOps.
A combinação da extração de sinais baseada em expressões regulares com o raciocínio LLM nos permite identificar esses padrões na fase de solicitação de pull request, antes que cheguem à produção. O repositório inclui o modelo de ameaças completo, o conjunto de testes e exemplos de diferenças, caso você queira se aprofundar nos detalhes ou adaptá-lo ao seu próprio ambiente.
Para começar, consulte o repositório cicd-abuse-detector para obter instruções de configuração, o modelo de ameaças completo e exemplos de diferenças. Estamos sempre interessados em conhecer novos padrões de ataque e ideias de detecção. Converse conosco em nosso Slack da comunidade e faça perguntas em nossos fóruns de discussão.
Abuso de CI/CD por meio do MITRE ATT&CK
Utilizamos a estrutura MITRE ATT&CK para mapear as táticas, técnicas e procedimentos que os adversários usam contra pipelines de CI/CD.
Táticas
| Tática | Relevância CI/CD |
|---|---|
| Acesso por credenciais (TA0006) | Extraindo segredos de ambientes de CI |
| Execução (TA0002) | Executando comandos em executores de pipeline |
| Persistência (TA0003) | Gatilhos agendados, fluxos de trabalho baseados em cron |
| Evasão de Defesa (TA0005) | Manipulação de timestamps de commits, evasão de mascaramento de logs |
| Acesso inicial (TA0001) | Credenciais de desenvolvedor comprometidas, phishing para PATs |
| Movimento Lateral (TA0008) | Utilizando credenciais de nuvem coletadas para mudar de rumo. |
Técnicas
| Técnica | Aplicação CI/CD |
|---|---|
| T1552: Credenciais não seguras | Segredos expostos em variáveis de ambiente de CI, artefatos e memória do executor. |
| T1195.002: Cadeia de Suprimentos de Software de Compromisso | Ações, dependências e arquivos de bloqueio corrompidos |
| T1059: Interpretador de Comando e Script | curl |
| T1070.006: Timestamp | Datas de commit retroativas para evitar revisão. |
| T1098: Manipulação de Contas | Elevação de permissões via write-all, id-token: write |
| T1078: Contas Válidas | PATs de desenvolvedor roubados foram usados para modificar fluxos de trabalho. |
Referências
Os seguintes itens foram referenciados ao longo da pesquisa acima:
- 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
Sobre o Elastic Security Labs
O Elastic Security Labs é o braço de inteligência de ameaças da Elastic Security dedicado a criar mudanças positivas no cenário de ameaças. O Elastic Security Labs fornece pesquisas publicamente disponíveis sobre ameaças emergentes com uma análise dos objetivos estratégicos, operacionais e táticos do adversário e, em seguida, integra essa pesquisa com os recursos integrados de detecção e resposta do Elastic Security.
Siga o Elastic Security Labs no Twitter @elasticseclabs e confira nossa pesquisa em www.elastic.co/security-labs/.