Como verificar que um artefato do GitHub Actions foi construído por você, não por um invasor
Ataques à cadeia de suprimentos já se tornaram há muito tempo de teoria para uma dura realidade. Digamos que um usuário baixe um binário pré-construído da seção Releases no GitHub. Como ele pode verificar que o arquivo foi realmente construído pelo servidor CI a partir do código-fonte de um commit específico, e não carregado por um hacker que obteve acesso à conta do desenvolvedor?
Para resolver esse problema, o GitHub lançou uma action especial actions/attest-build-provenance. Vamos analisar como ela funciona, por que as assinaturas do Sigstore são necessárias e por que você precisará de uma ferramenta ligeiramente diferente ao criar novos pipelines.
Onde vincular a assinatura
A essência da assinatura de procedência é bastante simples. Cada arquivo finalizado precisa de um passaporte digital. Este documento confirma: o artefato com um hash específico foi construído dentro de um workflow específico, em um repositório específico e em um commit específico.
A ferramenta gera um manifesto de acordo com o padrão in-toto e a especificação SLSA (Supply-chain Levels for Software Artifacts). Então acontece a parte mais interessante: assinar esse manifesto.
Em vez de forçar os desenvolvedores a gerar chaves PGP de longa duração e armazená-las em secrets do repositório, é usada a arquitetura Sigstore. A action solicita um token OIDC temporário do GitHub Actions e o troca por um certificado de assinatura de curta duração.
Para repositórios públicos, a assinatura é gerada através do serviço público Sigstore, e os dados sobre ela terminam no log transparente Rekor. Se o repositório for privado, o GitHub usa sua própria instância Sigstore privada (este recurso está disponível no plano Enterprise Cloud).
Uma pequena surpresa na documentação
Se você abrir o repositório oficial do projeto, verá uma nota importante bem no início do README.
A partir da versão quatro, actions/attest-build-provenance se transformou em um wrapper simples sobre a action base actions/attest. Os desenvolvedores do GitHub afirmam explicitamente: se você está mantendo pipelines antigos, pode deixar tudo como está. Mas para novos projetos, você deve começar diretamente com actions/attest.
Por que o GitHub adicionou uma camada extra? Inicialmente, a equipe estava construindo uma ferramenta de nicho apenas para procedência de build. Mais tarde, surgiu o desejo de assinar não apenas binários, mas também SBOMs (listas de dependências) ou resultados de varredura de vulnerabilidades. Foi assim que apareceu o actions/attest mais universal, e a action antiga foi descontinuada como sinônimo.
Como ficou a configuração
Em versões mais antigas da action, a lógica em .github/workflows/build.yml era comprimida em apenas algumas linhas após a etapa de build do artefato.
O que é importante aqui são as permissões id-token: write e attestations: write. Sem a primeira opção, o workflow não conseguirá obter um token OIDC para assinatura sem senha via Sigstore, e sem a segunda, ele não carregará o resultado para a API de Atestações do GitHub.
Como verificar a autenticidade do artefato
Após a atestação ser criada e vinculada ao repositório, qualquer usuário ou script de verificação pode verificar o arquivo localmente. Para isso, é usado o utilitário oficial GitHub CLI.
O comando de verificação fica assim:
gh attestation verify app.sh --owner my-organization
Se o arquivo não foi alterado e foi construído na organização especificada, a CLI exibirá informações sobre o commit e o certificado de assinatura. No entanto, se o arquivo foi modificado mesmo que minimamente, a verificação falhará com um erro.
Vale a pena implementar
Se você está desenvolvendo uma biblioteca de código aberto ou ferramenta CLI, gerar atestações dá aos usuários uma maneira fácil de verificar a segurança dos seus lançamentos.
Por outro lado, se você tem um projeto interno pequeno sem requisitos rígidos de segurança da cadeia de suprimentos, adicionar etapas extras ao seu CI pode ser um exagero.
Para novos workflows, use actions/attest diretamente em vez de actions/attest-build-provenance. A funcionalidade principal permanecerá a mesma, mas você estará usando uma ferramenta atualizada sem wrappers descontinuados.
Projetos relacionados