Sobre este conteúdo

Este artigo é uma leitura prática de SLSA v1.0 e do ecossistema Sigstore para times de engenharia de plataforma, AppSec e DevSecOps. Os comandos e snippets seguem comportamento documentado das ferramentas, mas versões mudam — sempre confira a documentação oficial do Cosign, do slsa-github-generator e do policy-controller antes de promover para produção.

Por que proveniência verificável virou requisito

Os ataques mais relevantes da última década não exploraram apenas vulnerabilidades em código — eles exploraram confiança implícita na cadeia de produção. SolarWinds (2020) injetou backdoor no build pipeline da Orion, distribuindo malware via update assinado legitimamente. Codecov (2021) teve o uploader Bash modificado e exfiltrou variáveis de ambiente de milhares de CIs. ua-parser-js (2021) e event-stream (2018) tiveram pacotes npm comprometidos via takeover de mantenedor ou de dependência transitiva. Log4Shell (Log4j) não foi supply chain stricto sensu, mas exibiu como uma vulnerabilidade em dependência ubíqua se propaga em horas para milhões de sistemas.

O padrão comum: o artefato final passou por todos os controles tradicionais (scanner SAST, antivírus, assinatura do publisher) e ainda assim continha código malicioso. Os controles olhavam o artefato, não o processo que o produziu. Quando o atacante compromete o builder, o artefato pode estar limpo no scanner e ainda ser hostil.

A resposta da indústria — formalizada na OpenSSF, na ordem executiva norte-americana 14028 e em legislações europeias subsequentes — foi exigir proveniência verificável: o artefato deve vir acompanhado de uma declaração assinada de quem o produziu, a partir de qual código-fonte, em qual ambiente, com quais dependências. E essa declaração precisa ser verificável de forma criptograficamente forte, idealmente sem depender de gestão manual de chaves pelo desenvolvedor.

Esse é o problema que SLSA e Sigstore resolvem juntos: SLSA define o que precisa ser garantido; Sigstore oferece a infraestrutura para assinar e verificar sem fricção operacional.

SLSA v1.0: framework, tracks e níveis

SLSA (Supply chain Levels for Software Artifacts, pronuncia-se "salsa") é um projeto da OpenSSF que define níveis incrementais de garantia sobre a cadeia de produção de software. A versão 1.0, publicada em junho de 2023, reorganizou o framework em tracks — cada track foca em uma propriedade específica e tem seus próprios níveis. Hoje o track maduro e estabilizado é o Build Track, que trata do processo de build e da proveniência produzida.

NívelO que exigeOnde estamos
Build L0Nenhum requisito. Não há proveniência verificável.Estado padrão de projetos sem maturidade de supply chain.
Build L1Proveniência existe e é distribuída com o artefato. Pode ser gerada manualmente ou pelo dev.Documenta a intenção; não previne falsificação por atacante interno.
Build L2Proveniência é gerada por uma plataforma de build hospedada (não pelo dev na máquina) e assinada por essa plataforma.O atacante precisa comprometer a plataforma para falsificar. Alcançável via GitHub Actions com actions/attest-build-provenance.
Build L3Builder fornece isolamento entre execuções e não-falsificabilidade da proveniência. Um job não pode forjar provenance de outro.Exige uso de geradores oficiais (ex.: slsa-github-generator em job dedicado e isolado). Estado da arte hoje.

Há discussão na comunidade sobre tracks adicionais (Source Track para garantias sobre o repositório de código, Dependencies Track para a árvore de dependências), mas em 2026 a recomendação prática é: foque em Build L2 como meta inicial e em L3 para artefatos críticos. Versões anteriores do SLSA (pré-1.0) mencionavam um L4 que foi removido — não persiga L4, ele não existe na especificação atual.

Build provenance e o formato in-toto

Proveniência, no contexto SLSA, é uma attestation: uma declaração estruturada, assinada, que descreve como um artefato foi produzido. O formato de referência é o in-toto attestation framework — JSON com dois campos centrais:

  • subject — o que está sendo atestado (lista de artefatos com seus digests SHA-256);
  • predicate — o conteúdo da declaração, cujo schema é definido pelo predicateType. Para SLSA, é https://slsa.dev/provenance/v1.

Um predicate SLSA v1.0 contém, entre outros campos, buildDefinition (qual builder, qual workflow, qual ref/commit, quais parâmetros e entradas externas) e runDetails (qual invocação específica, metadados, dependências resolvidas). Em build do GitHub Actions, o predicate referencia o repositório, o SHA do commit, o nome do workflow, o ref que disparou — tudo o que o verificador precisa para responder "esse binário veio mesmo daquele código?".

A attestation é envelopada em DSSE (Dead Simple Signing Envelope) e assinada. No fluxo Sigstore, a assinatura é keyless (próxima seção). A entrada é gravada no Rekor e a attestation pode ser anexada à imagem como artefato OCI ou distribuída separadamente.

Sigstore: Cosign, Fulcio e Rekor

Sigstore é um projeto da OpenSSF que oferece infraestrutura para assinar e verificar artefatos de software sem que cada desenvolvedor precise gerenciar chaves privadas de longa duração. Tem três componentes principais:

Cosign

CLI em Go que assina, atesta e verifica artefatos. Funciona com imagens OCI, blobs arbitrários e attestations in-toto. É a interface que o usuário toca.

Fulcio

CA que emite certificados X.509 de curta duração (cerca de 10 minutos) baseados em prova OIDC. O certificado vincula uma chave efêmera a uma identidade (e-mail, workflow, account).

Rekor

Log de transparência público, append-only, baseado em Trillian (Google). Toda assinatura Sigstore é gravada lá. Permite verificação pública e detecção de assinaturas indevidas pela própria identidade legítima.

Trust root

A raiz de confiança Sigstore é mantida pela comunidade (TUF). O cliente Cosign sabe verificar a cadeia Fulcio + Rekor + identidade OIDC contra essa raiz, sem configuração extra.

A instância pública é fulcio.sigstore.dev + rekor.sigstore.dev e é gratuita. Para ambientes que exigem soberania de dados ou maior controle, é possível operar uma instância privada — todas as três peças têm Helm charts oficiais. Em 2026, a maioria das organizações começa pela instância pública e migra para privada apenas quando há requisito regulatório explícito.

Como funciona o keyless signing na prática

O fluxo keyless elimina a necessidade de armazenar uma chave privada de longa duração. Em vez disso, a identidade do signatário é provada via OIDC e uma chave efêmera é gerada apenas para aquela operação. Passo a passo:

1

Geração da chave efêmera

O Cosign gera localmente um par ECDSA P-256 que existirá apenas em memória pelo tempo da operação. Nunca é persistido.

2

Prova de identidade via OIDC

O Cosign abre o navegador (em uso humano) ou consome o token de ambiente (em CI). O signatário se autentica em um provedor OIDC suportado: Google, GitHub Actions (token automático), GitLab, Azure, Microsoft, Okta. O retorno é um ID token contendo a identidade (e-mail, ou workflow + repo + ref no caso de Actions).

3

Emissão do certificado pelo Fulcio

O Cosign envia ao Fulcio o ID token e a chave pública efêmera. O Fulcio valida o token, extrai a identidade e emite um certificado X.509 com validade de aproximadamente 10 minutos, contendo essa identidade como extensão SAN.

4

Assinatura e gravação no Rekor

O Cosign assina o digest do artefato (ou a envelope DSSE da attestation) com a chave efêmera, e submete a assinatura + certificado ao Rekor. O Rekor retorna uma inclusion proof — prova criptográfica de que a entrada foi incluída no log.

5

Descarte da chave

A chave privada efêmera é descartada. O certificado expira em minutos. A prova permanente fica no Rekor: digest do artefato + identidade do signatário + timestamp confiável.

Na verificação, o consumidor não precisa de chave pública nenhuma do signatário. Ele apenas declara qual identidade espera (ex.: "workflow release.yml do repo org/produto no branch main") e o Cosign confirma contra Rekor e Fulcio que existe uma assinatura compatível para aquele digest.

Comandos típicos (versões recentes do Cosign — 2.x — habilitam keyless por default; em versões anteriores era preciso COSIGN_EXPERIMENTAL=1):

# Assinatura keyless de uma imagem OCI
cosign sign ghcr.io/minha-org/api@sha256:abc123...

# Verificação contra uma identidade GitHub Actions específica
cosign verify \
  --certificate-identity=https://github.com/minha-org/api/.github/workflows/release.yml@refs/heads/main \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  ghcr.io/minha-org/api@sha256:abc123...

# Geração de attestation in-toto a partir de um predicate SLSA
cosign attest \
  --predicate provenance.json \
  --type slsaprovenance \
  ghcr.io/minha-org/api@sha256:abc123...

# Verificação de attestation
cosign verify-attestation \
  --type slsaprovenance \
  --certificate-identity=https://github.com/minha-org/api/.github/workflows/release.yml@refs/heads/main \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  ghcr.io/minha-org/api@sha256:abc123...

Cuidado com tag vs digest

Sempre assine e verifique pelo digest (@sha256:...), não pela tag. Tags são mutáveis: um atacante com push pode reapontar v1.2.3 para outra imagem após a assinatura, criando um TOCTOU. Em pipelines, capture o digest no build e propague-o até o deploy.

Implementação em GitHub Actions

GitHub Actions é hoje o caminho de menor fricção para sair de L0 e chegar a L2 com poucos passos. Dois blocos costumam coexistir em um workflow de release: (a) build + push da imagem com captura do digest, (b) geração da proveniência SLSA com actions/attest-build-provenance@v1. A action assina via keyless usando o OIDC token do próprio workflow e anexa a attestation à imagem no registry.

Snippet exemplificativo (estrutura essencial — adapte aos seus secrets, labels e tags):

name: release

on:
  push:
    tags: ['v*']

permissions:
  contents: read
  id-token: write       # necessário para OIDC keyless
  packages: write       # push no GHCR
  attestations: write   # gravar attestation

jobs:
  build-and-sign:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}

      - name: Gerar proveniência SLSA
        uses: actions/attest-build-provenance@v1
        with:
          subject-name: ghcr.io/${{ github.repository }}
          subject-digest: ${{ steps.build.outputs.digest }}
          push-to-registry: true

      - name: Assinar a imagem (cosign keyless)
        env:
          IMAGE: ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}
        run: cosign sign --yes "$IMAGE"

Esse workflow entrega Build L2: a proveniência é gerada pela plataforma GitHub (não pela máquina do dev), assinada keyless contra a identidade do workflow, e gravada no Rekor. O consumidor verifica com cosign verify + cosign verify-attestation usando a identidade do workflow esperado.

O ecossistema DevSecOps shift-left ganha aqui uma camada nova: além de scanners e SAST/DAST/IAST, o pipeline produz evidência criptográfica de origem que segue o artefato até produção.

Verificação em Kubernetes

Assinar imagens só tem valor se o cluster rejeita o que não está assinado ou não tem proveniência válida. Três caminhos são comuns em 2026:

FerramentaModeloQuando usar
policy-controller (Sigstore)Admission controller dedicado, com CRD ClusterImagePolicy que declara identidades aceitáveis e attestations exigidas.Quando o requisito é específico para Sigstore e você quer integração nativa com Cosign sem traduzir conceitos.
KyvernoEngine de política genérica com regra verifyImages que faz a chamada Cosign internamente.Quando você já usa Kyverno para outras políticas (PSA, network, RBAC) e quer concentrar tudo numa engine.
OPA GatekeeperEngine baseada em Rego; verificação de assinatura usa providers externos ou ext-authz.Quando a organização já padronizou em OPA e tem time fluente em Rego. Menos ergonômico que os anteriores para Sigstore específico.

Exemplo de política Kyverno que exige assinatura keyless válida para uma identidade GitHub Actions específica (esqueleto — adapte ao seu schema e versão):

apiVersion: kyverno.io/v2beta1
kind: ClusterPolicy
metadata:
  name: exigir-assinatura-keyless
spec:
  validationFailureAction: Enforce
  webhookTimeoutSeconds: 30
  rules:
    - name: verificar-imagens-produtivas
      match:
        any:
        - resources:
            kinds: ["Pod"]
            namespaces: ["prod-*"]
      verifyImages:
        - imageReferences:
            - "ghcr.io/minha-org/*"
          attestors:
            - entries:
                - keyless:
                    subject: "https://github.com/minha-org/api/.github/workflows/release.yml@refs/heads/main"
                    issuer: "https://token.actions.githubusercontent.com"

O cluster passa a rejeitar, no admission, qualquer pod em namespaces prod-* que tente puxar uma imagem ghcr.io/minha-org/* sem assinatura compatível. Comece com validationFailureAction: Audit para medir impacto e migre para Enforce após estabilizar.

Como passar de L2 para L3

Build L2 é alcançável quase trivialmente em pipelines hospedados modernos. Build L3 exige um salto qualitativo: o builder precisa garantir isolamento (um job não pode interferir em outro) e não-falsificabilidade da proveniência (o código de aplicação não pode forjar a attestation de si mesmo).

Em GitHub Actions, o caminho prático é o slsa-github-generator: um reusable workflow oficial mantido pela OpenSSF que executa em um job separado, com permissões restritas, sem acesso ao código do build. Ele recebe os hashes do artefato produzido, monta a attestation SLSA e a assina keyless, sem rodar nada do projeto. Como o gerador roda em workflow reusable com SHA fixo e identidade própria, a proveniência fica vinculada a essa identidade — não à do workflow do projeto, o que impede que código malicioso no repositório falsifique a attestation.

Práticas adicionais para sustentar L3 ao longo do tempo:

  • Hermeticidade do build — entradas declaradas, sem network access durante a build, dependências resolvidas em proxy controlado;
  • Reprodutibilidade — build do mesmo commit em ambiente equivalente produz o mesmo hash;
  • Pin de actions de terceiros por commit SHA, nunca por tag mutável;
  • Segregação de segredos de release — credenciais de push só existem no job de release, não no job de build;
  • Revisão obrigatória de mudanças no workflow de release (CODEOWNERS).

Aderência regulatória: EO 14028, CRA, NIS2

Proveniência verificável saiu do campo de "best practice opcional" e entrou no campo regulatório em múltiplas jurisdições. Três marcos relevantes:

  • EO 14028 (Estados Unidos, 2021) — Executive Order sobre cibersegurança da União que exigiu, via guidance NIST SP 800-218 (SSDF) e M-22-18 / M-23-16 da OMB, que fornecedores de software ao governo federal atestem práticas seguras de desenvolvimento. SBOM e self-attestation de aderência ao SSDF são exigidos; SLSA é referenciado como caminho técnico aceitável para evidenciar várias dessas práticas.
  • CRA — Cyber Resilience Act (UE, 2024) — regula produtos com elementos digitais colocados no mercado europeu. Fabricantes terão de fornecer SBOM, gerir vulnerabilidades durante o ciclo de vida e demonstrar processo de desenvolvimento seguro. Proveniência verificável é um habilitador natural — veja o detalhamento em CRA para fabricantes.
  • NIS2 (UE, 2024) — obriga entidades essenciais e importantes a gerirem riscos de cadeia de suprimentos, incluindo a integridade dos componentes de software adquiridos. Verificação de assinatura e proveniência em admission de produção é um controle direto contra esse requisito.

No Brasil, ainda não há regulação setorial que cite SLSA nominalmente, mas o tema entra por dois caminhos práticos: (1) contratos com órgãos públicos e empresas que vendem para a UE ou os EUA passam a exigir SBOM e attestation; (2) auditorias do BCB e da ANPD valorizam evidência de controle sobre cadeia de prestadores de software, e proveniência cumpre esse papel.

Roadmap de adoção: Crawl, Walk, Run

Adoção big bang fracassa. O caminho que funciona em organizações com dezenas de pipelines é incremental, em três fases.

1

Crawl — assinatura básica e visibilidade

Habilite cosign sign keyless nos pipelines das 3-5 imagens mais críticas. Não imponha verificação no cluster ainda — apenas comece a gerar assinaturas. Configure dashboards para mostrar quais imagens em produção têm e quais não têm assinatura. Treine os times de plataforma e AppSec no ferramental.

2

Walk — proveniência SLSA L2 e enforcement em audit

Adicione actions/attest-build-provenance aos workflows. Habilite Kyverno ou policy-controller em modo Audit nos namespaces produtivos — você verá quem está fora de conformidade sem bloquear deploys. Use o período de audit (4-8 semanas) para remediar pipelines legados e padronizar identidades aceitáveis.

3

Run — enforcement em produção e L3 para artefatos críticos

Vire o modo para Enforce em namespaces produtivos. Migre os builds mais sensíveis (componentes de segurança, gateways, runtime de pagamento) para slsa-github-generator para atingir L3. Acrescente verificação de attestation além de assinatura simples. Documente o processo de exceção para emergências e CSIRT.

O glossário de cibersegurança tem verbetes para os termos centrais (SBOM, attestation, OIDC, transparency log) e o hub de comparadores ajuda a posicionar SLSA contra outras camadas de controle AppSec.

Perguntas frequentes

O que é SLSA e para que serve?

SLSA (Supply chain Levels for Software Artifacts) é um framework da OpenSSF que define níveis incrementais de garantia sobre a cadeia de produção de software. A versão 1.0 organiza requisitos em tracks; o Build Track vai de L0 (sem proveniência) a L3 (builder isolado e proveniência não-falsificável). O objetivo é dar ao consumidor de um artefato evidência verificável de quem o construiu, a partir de qual código e em qual ambiente.

Qual a diferença entre assinatura tradicional e assinatura keyless do Sigstore?

Na tradicional, o desenvolvedor mantém uma chave privada de longa duração — risco operacional (rotação, vazamento, perda). No keyless do Sigstore, a identidade é provada via OIDC, o Fulcio emite um certificado X.509 de curta duração (~10 min), a assinatura é feita com chave efêmera e a entrada é gravada no Rekor. A verificação posterior usa apenas a identidade OIDC e a entrada no Rekor, sem gestão de chaves.

Cosign assina apenas imagens de container?

Não. Cosign começou com foco em imagens OCI mas hoje assina e atesta qualquer artefato — binários, arquivos, blobs, módulos. Para artefatos não-OCI, use cosign sign-blob e cosign attest-blob. SLSA provenance pode ser anexada a imagens, releases do GitHub e qualquer artefato com hash conhecido.

Como SLSA L3 é diferente de L2 na prática?

L2 exige que a proveniência seja gerada por uma plataforma de build hospedada e assinada por essa plataforma. L3 adiciona isolamento entre execuções e prevenção de tampering: um job não pode falsificar a proveniência de outro. Em GitHub Actions, L3 envolve usar reusable workflows confiáveis como o slsa-github-generator, que executa em job separado e isolado.

Sigstore e SLSA são a mesma coisa?

Não. SLSA é um framework de requisitos sobre o processo de build e a proveniência produzida. Sigstore é a infraestrutura técnica (Cosign + Fulcio + Rekor) que operacionaliza assinatura e attestation sem gestão de chaves. Eles se complementam — Sigstore é hoje o caminho mais prático para assinar a proveniência exigida pelo SLSA.

Como começar com SLSA sem um big bang?

Crawl: introduza cosign sign keyless em imagens-chave e exija verificação básica no cluster. Walk: adicione actions/attest-build-provenance para gerar provenance SLSA L2 e passe a verificar provenance no deploy. Run: migre os builds críticos para o slsa-github-generator (L3), implemente políticas Kyverno ou policy-controller que exigem provenance L3, e amarre release approvals à verificação automática.

Conclusão

A defesa contra ataques de supply chain saiu da camada do scanner e desceu para a camada do processo. Não basta mais verificar o que o artefato é — é preciso verificar como ele veio a existir. SLSA dá o vocabulário e os níveis; Sigstore dá a infraestrutura prática e sem fricção. Juntos, tornam viável que cada deploy em produção carregue prova criptográfica de origem.

Para o engenheiro de plataforma, o trabalho desta sprint é claro: identifique três pipelines críticos, habilite cosign sign keyless e actions/attest-build-provenance, e configure verificação em modo Audit nos namespaces produtivos. Para o líder de AppSec, é hora de codificar o requisito em política e amarrar release approvals à verificação automática. Para o líder técnico de produto, é momento de incluir proveniência verificável nos contratos com terceiros e nos requisitos de aquisição — antes que a regulação imponha um cronograma mais apertado.

O custo de adoção em 2026 é baixo, o ferramental está maduro e a infraestrutura pública do Sigstore funciona com SLA razoável. A janela para adotar de forma controlada — em vez de correr atrás de auditoria — é agora.

Referências

Avaliação de maturidade de supply chain de software

Diagnóstico independente da sua cadeia de build, pipelines e verificação em produção. Mapeia gaps frente a SLSA v1.0 e a requisitos regulatórios emergentes, com roadmap pragmático Crawl/Walk/Run.

Falar com Especialista