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
- O runner baixa e instala o agente Sentinel usando a chave de API.
- O agente analisa os manifestos do projeto e monta um SBOM CycloneDX.
- Ele enriquece os componentes com dados do OSV e aplica a validação CISA KEV.
- Ele envia o SBOM (e as eventuais ocorrências de secrets mascaradas) para a API da WASViking por REST sobre HTTPS.
- A API valida a cota, registra o snapshot do SBOM, detecta drift de componentes e promove os achados.
- 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-gappedgarante 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-sentinelpossa 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 comBearer. 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.
Settings → System Settings → API Keys.
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,vendore 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-nameexplí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.
