Webinar em inglêsWebinar com Jason Lee, quarta, 14/10Your newest insider is an AI agent.Jason LeeFormer CISO, Zoom & SplunkInscreva-se

As tuas pipelines são código. Por isso lemo-las.

Os teus ficheiros de workflow lidos como código: injeção, actions não fixadas, tokens e confiança, cada um com a sua correção.

checkout-apiCI/CDProjeto de demonstração
  • CríticaInjeção num workflowrelease.yml:24

    O título da pull request chega a run: na shell.

    run: echo "${{ github.event.pull_request.title }}"env:  TITLE: ${{ github.event.pull_request.title }}run: echo "$TITLE"

    Correção prontaO título passa para uma variável de ambiente, fora da shell.

As falhas do pipeline, encontradas no ficheiro.

  • Injeção num workflow

    • ${{ github.event.pull_request.title }}
  • Actions não fixadas

    • actions/checkout@v3
    • actions/setup-node@main
  • Tokens com privilégios a mais

    • permissions: write-all
  • Confiança OIDC

    • "sub": "repo:acme/*"

A injeção, corrigida no workflow.

Tal como está escrito

run: echo "${{ github.event.pull_request.title }}"

O título da pull request chega a run: na shell.

Com a correção

env:  TITLE: ${{ github.event.pull_request.title }}run: echo "$TITLE"

O título passa para uma variável de ambiente, fora da shell.

Corrigido pelo teu agente, na sessão.

O teu agente lê estas falhas enquanto escreve e corrige-as na mesma sessão.

  1. CI/CDAnalisa o repositório em cada push.Detetada
  2. VibeDefendPassa a descoberta ao teu agente de código.Servida
  3. O teu agenteCorrige-a na sessão.Corrigida
  4. CommitEntra sem a falha.Limpo
  • Claude Code
  • Cursor
  • Windsurf
  • GitHub Copilot
  • OpenAI Codex

Começa por um repositório.

Liga o GitHub, o GitLab, o Bitbucket ou o Azure DevOps, escolhe um repositório e a primeira análise arranca.

Em detalhe

Seis falhas de pipeline, encontradas no ficheiro.
  • Injeção num workflow

    Dados de eventos, nomes de ramos ou títulos de pull request que chegam a um bloco run:.

    CWE-77, CWE-78
  • Actions não fixadas

    @v3, @main, @latest: cada referência flutuante é um futuro incidente de supply chain.

  • Tokens com privilégios a mais

    Sem bloco permissions:, ou com permissões de escrita que um job nunca usa.

  • Confiança OIDC

    Identidade federada do GitHub, GitLab ou CircleCI para a AWS, Azure e GCP, concedida de forma demasiado ampla.

  • Fugas de segredos

    echo $SECRET, segredos passados como argumentos, esquecidos em artefactos ou em camadas de imagem.

  • Envenenamento de cache e de artefactos

    Pull requests não fiáveis que escrevem em caches lidas pelos ramos protegidos.

Tudo o que verifica

Apanha a má configuração antes de o runner correr.

A maioria dos incidentes de pipeline já é visível no YAML. Lemo-lo como o leria um atacante.

  • Pipelines tratadas como código

    Os ficheiros de workflow são examinados com o mesmo rigor que o código da tua aplicação: análise do AST, propagação de taint e análise de source a sink.

  • GitHub Actions, GitLab CI, Jenkinsfile

    Parsers dedicados para os dialetos de CI em que hoje se escreve a maioria das pipelines, incluindo workflows reutilizáveis, cadeias include: do GitLab e Jenkinsfile (Groovy declarativo e scripted).

  • As descobertas, na PR

    Cada descoberta chega como comentário na linha do YAML afetada, no mesmo sítio que as do SAST.

Seis falhas, lidas no ficheiro.

Convertemos os teus workflows num AST e num grafo de fluxo de dados e aplicamos-lhes os nossos próprios packs de regras.

  • Injeção em workflows (CWE-77 / 78)

    Sempre que interpolas ${{ github.event.* }}, nomes de branch, títulos de PR ou o texto das issues num bloco run:, abres a porta a uma injeção de shell na tua própria pipeline.

  • Actions não fixadas e não fiáveis

    @v3, @main, @latest: cada referência flutuante é um futuro incidente de supply chain.

  • Tokens com privilégios a mais

    Por omissão, as permissões do GITHUB_TOKEN são write para quase tudo. Detetamos permissions: por definir e permissões amplas que não usas, e recomendamos o mínimo necessário para cada job.

  • Confiança OIDC mal configurada

    Identidade federada com AWS, Azure e GCP a partir do GitHub, do GitLab e do CircleCI.

  • Padrões de fuga de segredos

    echo $SECRET, segredos passados como argumentos posicionais, segredos gravados em artefactos, segredos embutidos em camadas de contentor.

  • Envenenamento de cache e artefactos

    PR não fiáveis a escrever em caches lidas por branches protegidos. Runners self-hosted reutilizados sem isolamento.

Do YAML à correção
  • O YAML é inseguro.

    Trigger inseguro, escrita, action sem fixar.

  • Julgado antes de correr.

    Estático, no próprio ficheiro, sem pipeline.

  • Fixado e restringido.

    SHA fixado, só leitura, inputs isolados.

Liga o repo, o resto é automático.

Liga o GitHub ou o GitLab. Os nossos scanners leem os ficheiros de pipeline e correm a cada push (ou a pedido). Nada para instalar na tua CI, nenhum passo com runner privilegiado. As descobertas chegam ao dashboard unificado e à revisão da tua PR.

Seis dialetos de CI alimentam um único parser: GitHub Actions, GitLab CI, Bitbucket, Azure DevOps, Jenkins, CircleCI.

O commit a3f9c2e toca no release.yml. Duas execuções saem do build: #4821 e #4822.

Na barreira, o release.yml é lido como o leria um atacante: trigger, permissões, cada uses: e run:.

#4821 fica bloqueada: pull_request_target com contents: write e uma action não fixada nunca chegam ao job de deploy.

#4822 segue para prod-eu: SHA fixado, token só de leitura, o título da PR fora da shell.

Perguntas frequentes sobre o scanner CI/CD.

A CybeDefend analisa os ficheiros da pipeline sem ser um passo dentro dela?
Exato. Ligas o repositório uma única vez. Os nossos scanners leem diretamente .github/workflows, .gitlab-ci.yml, Jenkinsfile e os restantes, e publicam as descobertas como comentários na linha afetada e no dashboard unificado. Não é preciso acrescentar nenhum passo à tua pipeline nem instalar um runner privilegiado.
Que formatos de pipeline são suportados?
Workflows do GitHub Actions (incluindo actions compostas e workflows reutilizáveis), YAML do GitLab CI (incluindo cadeias `include:`) e Jenkinsfile (Groovy declarativo e scripted). Também lemos as definições de actions (action.yml e os wrappers de Dockerfile), por isso seguimos os fluxos de taint entre actions. Acrescentamos outros dialetos a pedido dos clientes.
Como se deteta uma injeção em workflows se só é acionada com certos payloads de eventos?
Não precisamos do payload. Tratamos como não fiável cada valor que vem de `github.event.*`, `inputs.*`, `head_ref`, `pull_request.title/body` e das refs de branch e de tag de um fork, e seguimo-lo através de `env:`, `with:`, dos valores de output e das fronteiras das actions compostas. Se esse valor chegar a um bloco `run:`, a um `eval` numa action de JavaScript ou a um comando com substituição de shell, é uma descoberta, quer já tenhas sido atacado ou não.
A CybeDefend deteta GitHub Actions maliciosas ou com typosquatting?
Sim. Cada entrada `uses:` é cruzada com o feed de actions maliciosas da OpenSSF, a lista de publicadores verificados e as nossas próprias heurísticas de typosquatting sobre os nomes das actions. As tags não fixadas são assinaladas à parte, porque até uma action legítima se torna um risco de supply chain se não a fixares num SHA.
E os segredos nos ficheiros de workflow?
Tudo o que corresponde aos padrões de entropia e de fornecedor do nosso pack de regras de deteção de segredos é também assinalado nos ficheiros de CI/CD. Detetamos ainda segredos passados como argumentos posicionais da CLI (visíveis no `ps`), segredos escritos nos logs com `echo` e segredos embutidos nos inputs de workflows reutilizáveis. As descobertas são deduplicadas com as do scanner de segredos, para não as receberes duas vezes.
É possível analisar configurações de runners self-hosted?
Sim. Analisamos as diretivas `runs-on:`, detetamos runners que partilham o estado do sistema de ficheiros entre PR não fiáveis, assinalamos a falta de controlos do tipo `actions/cleanup` e avisamos sobre jobs que escalam para root ou montam o socket do Docker.