WASViking Docs
⌘K
Primeiros passos

SCA, SBOM e secrets no CI/CD com GitHub Actions

Gere um SBOM CycloneDX e procure secrets embutidos no código no seu pipeline do GitHub Actions com o WASViking Sentinel. Enriquece com OSV e CISA KEV, envia por HTTPS, faz o build falhar quando há dependências com vulnerabilidades conhecidas ou credenciais vazadas e publica na aba Security do GitHub.

Esta integração executa Análise de Composição de Software (SCA) e um scan de secrets dentro do seu runner do GitHub Actions. O WASViking® Sentinel lê os seus manifestos de dependências, monta um SBOM CycloneDX, enriquece esse SBOM com OSV e CISA KEV, procura credenciais embutidas no código em toda a árvore e faz o pipeline falhar quando há dependências com vulnerabilidades conhecidas ou secrets vazados, antes do merge.

Diferentemente do fluxo de DAST, não há túnel mTLS: o SBOM e as ocorrências de secrets são enviados por REST sobre HTTPS simples, com uma chave de API como credencial do tipo bearer. Nenhum código-fonte sai do runner, apenas o grafo de dependências (nomes e versões de pacotes) e as ocorrências de secrets mascaradas.

A configuração tem duas metades, e a ordem importa: configure o portal da WASViking primeiro (uma chave de API com os escopos ci:scan, sca:submit e secrets:submit) e depois conecte tudo ao GitHub Actions.

O que esta integração faz

  • Gera um SBOM CycloneDX 1.5 a partir dos seus manifestos (npm, pip, go, composer, Maven, gem, pub) a cada push e pull request.
  • Enriquece os componentes com OSV e CISA KEV (vulnerabilidades sabidamente exploradas).
  • Analisa a árvore de trabalho em busca de secrets embutidos no código e envia as ocorrências mascaradas.
  • Faz o build falhar por severidade com --fail-on, bloqueando releases vulneráveis antes do merge.
  • Emite SARIF 2.1.0 para o GitHub Code Scanning, além do JSON CycloneDX bruto.
  • Monta um inventário de software consolidado por organização e detecta drift entre envios consecutivos.
  • Provisiona e remove o agente a cada execução, sem credenciais persistentes no runner.
  • Oferece modo air-gapped para redes sem saída externa.

Como funciona

  1. O runner baixa e instala o agente Sentinel usando a chave de API.
  2. O agente analisa os manifestos do projeto e monta um SBOM CycloneDX.
  3. Ele enriquece os componentes com dados do OSV e aplica a validação CISA KEV.
  4. Ele envia o SBOM (e as eventuais ocorrências de secrets mascaradas) para a API da WASViking por REST sobre HTTPS.
  5. A API valida a cota, registra o snapshot do SBOM, detecta drift de componentes e promove os achados.
  6. O agente grava as saídas em SARIF e JSON, e o workflow envia o SARIF para o GitHub Code Scanning.

Postura de acesso

  • Apenas os manifestos e o grafo de dependências são lidos. Nenhum código-fonte, variável de ambiente do runner (além das chaves que você passa) ou arquivo fora de .wasviking/ é coletado.
  • Os valores brutos dos secrets nunca saem do runner; apenas as ocorrências mascaradas são enviadas.
  • O envio é feito por REST sobre HTTPS com uma chave de API como credencial bearer (sem túnel mTLS).
  • --air-gapped garante zero saída de rede externa (sem consulta ao OSV, sem envio).
  • Revogue o acesso a qualquer momento revogando a chave de API no portal.

Pré-requisitos

Requisito Detalhe
Plano WASViking Envios de SBOM habilitados (Pro ou superior).
Papel no portal Admin ou Manager, para emitir chaves de API.
Repositório no GitHub Permissão para criar secrets do Actions e arquivos em .github/.
Permissões do workflow contents: read e security-events: write (para o upload do SARIF).
Manifestos do projeto Pelo menos um lockfile suportado: package-lock.json, yarn.lock, pnpm-lock.yaml, requirements.txt, Pipfile.lock, go.sum, composer.lock, pom.xml, Gemfile.lock, pubspec.lock. O lockfile precisa estar commitado no repositório.
Runner Hospedado pelo GitHub (ubuntu-latest recomendado) ou self-hosted Linux x86_64.
Saída de rede HTTPS para api.wasviking.com, api.osv.dev e github.com na porta 443. Nenhuma conexão de entrada é necessária.

Não usa GitHub Actions? Estes gates rodam em qualquer sistema de CI em que o binário wasviking-sentinel possa ser executado. Há um exemplo completo para Bitbucket Pipelines, e a referência independente de fornecedor é wasviking-sentinel em CI/CD.


Passo 1: Crie uma chave de API para o pipeline (portal)

Uma única chave de API cobre o fluxo inteiro: ela baixa o instalador do agente e autentica os envios de SBOM e de secrets. Nenhum token do agente Sentinel participa desta integração.

Vá em Settings → System Settings → API Keys e clique em + New Key (nova chave).

Campo Valor
Label Algo identificável, por exemplo GitHub Actions SCA pipeline. Use uma chave por repositório para poder revogá-la sem afetar outros pipelines.
Scopes Selecione ci:scan (Trigger scans from a CI/CD pipeline, que também é o que autoriza o download do instalador do agente), sca:submit (Send SBOMs from the Sentinel agent. OWASP A06) e secrets:submit (Send hard-coded credential matches from the Sentinel agent. OWASP A07). Adicione apenas o que este pipeline precisa.
Expiration 90 dias é um padrão sensato; faça a rotação nessa cadência.

Salve e copie a chave uma única vez. Você vai colá-la no GitHub no Passo 2 como WASV_SCA_API_KEY. A mesma chave carrega os três escopos, então ela cobre a instalação do agente, o SBOM e o scan de secrets.

A WASViking autentica com o header Authorization: ApiKey <key>, não com Bearer. Você pode revisar ou ajustar os escopos de uma chave depois, em Edit; isso mantém o mesmo valor da chave, então o pipeline continua funcionando sem que o secret precise ser emitido de novo.

System Settings, aba API Keys, com a lista de chaves Settings → System Settings → API Keys.

Seletor de escopos da chave de API com os escopos do pipeline selecionados Selecione os escopos do pipeline ao criar a chave.


Passo 2: Adicione o secret no GitHub

Nunca faça commit de uma chave no repositório. Guarde-a como um secret criptografado do Actions.

No GitHub, vá em Settings → Secrets and variables → Actions → Secrets do repositório e adicione:

Nome Valor
WASV_SCA_API_KEY A chave de API do Passo 1 (carrega ci:scan, sca:submit e secrets:submit).

Use Secrets (criptografados), nunca Variables, para a chave. Para vários ambientes (staging, produção), prefira Environment secrets com revisores obrigatórios e regras de proteção de implantação.


Passo 3: Adicione o workflow

Crie .github/workflows/wasviking-sca.yml:

name: WASViking SCA

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  contents: read
  security-events: write
  actions: read

jobs:
  sca:
    runs-on: ubuntu-latest
    timeout-minutes: 25
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install WASViking Sentinel
        env:
          WASV_SCA_API_KEY: ${{ secrets.WASV_SCA_API_KEY }}
        run: |
          curl -fsSL -H "Authorization: ApiKey $WASV_SCA_API_KEY" \
            https://api.wasviking.com/api/v1/sentinel/install.sh | sh

      - name: Run WASViking SBOM (SCA)
        env:
          WASV_SCA_API_KEY: ${{ secrets.WASV_SCA_API_KEY }}
        run: |
          mkdir -p wasviking-reports
          ./.wasviking/wasviking-sentinel sbom \
            --api-key "$WASV_SCA_API_KEY" \
            --path . \
            --app-name "${{ github.repository }}" \
            --app-version "${{ github.sha }}" \
            --fail-on critical \
            --submit \
            --out ./wasviking-reports

      - name: Run WASViking secrets scan
        env:
          WASV_SCA_API_KEY: ${{ secrets.WASV_SCA_API_KEY }}
        run: |
          ./.wasviking/wasviking-sentinel secrets \
            --api-key "$WASV_SCA_API_KEY" \
            --path . \
            --fail-on high \
            --submit \
            --out ./wasviking-reports

      - name: Upload SARIF to GitHub code scanning
        if: always() && hashFiles('wasviking-reports/*.sarif') != ''
        uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: wasviking-reports
          category: wasviking-sca

      - name: Upload SBOM artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: wasviking-sbom
          path: wasviking-reports/

O upload para o Code Scanning (o passo do SARIF) exige o GitHub Advanced Security em repositórios privados. Se você não tem esse recurso, remova esse passo e use o artefato enviado e o portal no lugar dele.


Passo 4: Flags dos comandos

sbom (SCA / SBOM)

wasviking-sentinel sbom [flags]
Flag Obrigatória Descrição
--api-key Sim Chave de API com o escopo sca:submit.
--path Não Diretório analisado recursivamente em busca de manifestos. Padrão: diretório atual.
--app-name Não Nome do projeto incluído nos metadados do CycloneDX. Padrão: nome do diretório.
--app-version Não Versão do projeto nos metadados. Use ${{ github.sha }}.
--fail-on Não Limite único: critical, high, medium, low ou none. Lógica de "igual ou acima". Padrão: high.
--submit Não Envia o SBOM para a WASViking. Omita para uma execução apenas local.
--out Não Diretório de saída para o JSON CycloneDX e o SARIF. Padrão: diretório atual.
--air-gapped Não Totalmente offline. Sem consulta ao OSV e sem envio.

Saídas: wasviking-sbom.cdx.json (CycloneDX 1.5) e wasviking-sbom.sarif (SARIF 2.1.0).

Sem --app-name, o projeto recebe o nome do diretório de checkout. Quando esse diretório tem um nome de local de build (build, dist, target, vendor e similares), o agente usa o nome do repositório no CI no lugar, para que o inventário não se encha de entradas chamadas "build". Um --app-name explícito sempre prevalece, e é por isso que o workflow acima passa um.

secrets

wasviking-sentinel secrets [flags]

Analisa a árvore em busca de credenciais embutidas no código e envia ocorrências mascaradas (os secrets brutos nunca saem do runner). Aceita as mesmas flags --api-key (com secrets:submit), --path, --fail-on, --submit e --out. Os resultados aparecem no portal em Application Security → Hard-coded Secrets.

Exit codes

Código Significado
0 Sucesso. Nada igual ou acima do limite do --fail-on.
70 Gate de SCA: uma dependência sinalizada no KEV, igual ou acima do limite. Sabidamente explorada, trate como urgente.
71 Gate de SCA: achados iguais ou acima do limite, nenhum deles no KEV.
73 Gate de secrets: uma credencial confirmada como ativa pelo --verify.
74 Gate de secrets: ocorrências iguais ou acima do limite que não foram verificadas.
79 Falha de cobertura: a raiz do scan não pôde ser percorrida, então nada foi analisado. Não é retornado para um projeto vazio ou sem nenhum manifesto suportado. Veja Falhas de cobertura.
1 / 2 Erro operacional (manifesto ilegível, chave rejeitada, argumento inválido).

Uma falha no enriquecimento com OSV ou uma falha no envio não faz o build falhar. Ambas geram um aviso, mantêm os artefatos em disco e deixam o gate decidir com base no que a execução conseguiu enxergar.


Política de fail-on

--fail-on define a menor severidade que faz o build falhar; tudo o que está acima dela também falha.

Configuração Comportamento
--fail-on none Nunca falha. Apenas relatório.
--fail-on critical Falha apenas com severidade crítica.
--fail-on high Falha com severidade alta e crítica. Um bom padrão para PRs.
--fail-on medium Falha com severidade média e acima. Mais rigoroso, mais atrito.
--fail-on low Postura máxima. Use em projetos novos, sem dívida acumulada.

Um rollout prático: comece em high e depois aperte para medium quando a sua baseline de dependências estiver estável (normalmente, alguns sprints).

Modo air-gapped

Ambientes regulados (defesa, governo, saúde com dados sigilosos) costumam proibir saída externa. Execute o SBOM totalmente offline:

wasviking-sentinel sbom \
  --path . \
  --air-gapped \
  --out ./wasviking-reports

--air-gapped pula a consulta ao OSV e o envio, usando apenas os dados de KEV embutidos. Use em redes sigilosas sem saída, para validação local antes de enviar um artefato manualmente, ou em build farms isoladas.

O que é e o que não é coletado

A WASViking não coleta o código-fonte do seu repositório, variáveis de ambiente do runner além das chaves que você passa, conteúdo do sistema de arquivos do runner fora de .wasviking/ nem qualquer dado de produção. O SBOM contém apenas o grafo de dependências (nomes de pacotes, versões, licenças, hashes de manifestos); o scan de secrets envia apenas ocorrências mascaradas. Os dados são processados na região dos Estados Unidos, criptografados em trânsito (TLS 1.2+) e em repouso (AES-256), com retenção definida pelo seu plano. Um DPA e a residência de dados na União Europeia estão disponíveis sob solicitação; veja o Trust Center para o mapeamento completo de conformidade (ISO 27001, SOC 2, LGPD, GDPR, NIST SSDF, OWASP Top 10 A06/A07, OWASP DSOMM, elementos mínimos de SBOM da CISA).

Problemas comuns

Problema Causa provável
HTTP 401 Unauthorized Chave de API revogada, expirada ou sem ci:scan / sca:submit / secrets:submit. A WASViking usa Authorization: ApiKey <key>, não Bearer.
HTTP 402 quota exceeded Cota mensal de envios de SBOM atingida. Aguarde o próximo ciclo, faça upgrade ou compre um pacote add-on.
HTTP 413 payload too large SBOM acima de 100 MiB (raro). Reduza com --no-osv ou divida o monorepo.
manifest not detected Nenhum dos lockfiles suportados foi encontrado em --path.
Timeout do OSV api.osv.dev lento ou inacessível. Use --no-osv para um SBOM sem enriquecimento, ou --air-gapped.
Achados diferentes entre execuções Lockfile não determinístico (por exemplo, package-lock.json regenerado sem npm ci). Sempre faça commit dos lockfiles.
Erro no download do install.sh Política de rede bloqueando api.wasviking.com ou o bucket de releases.
Exit 70 inesperado em um PR pequeno Uma nova dependência transitiva chegou pelo lockfile e está no CISA KEV. Inspecione com npm ls <package> ou o equivalente.
Drift detected: yes em toda execução O seu conjunto de dependências está mesmo mudando a cada execução, normalmente por um lockfile regenerado durante o build. Instale com npm ci ou o equivalente e faça commit do lockfile. O drift compara os componentes com o envio anterior que tem o mesmo --app-name e ignora o --app-version.
Drift nunca é reportado O --app-name não é estável entre execuções, então cada envio inicia a própria linhagem, sem nada com que comparar. Derive o nome a partir do repositório, não do caminho de checkout.

Onde isto se encaixa na plataforma

  • O inventário de software fica em Inventory → SBOM; as ocorrências de secrets, em Application Security → Hard-coded Secrets.
  • O equivalente para DAST é DAST no CI/CD com GitHub Actions.
  • Os mesmos dois gates no ecossistema Atlassian estão em SCA, SBOM e secrets no CI/CD com Bitbucket Pipelines.
  • Prefere não mudar nada no pipeline? O Code Security executa os mesmos motores de SBOM e de secrets no lado do servidor, nos repositórios que você conecta pelo GitHub App ou pelo Bitbucket OAuth, na cadência do seu plano e a cada push; o gate no pipeline continua sendo a forma de bloquear um build.
  • O roteamento de alertas está documentado em Slack e Teams e Webhooks.