Porquê a CI
Porque a segurança da cadeia de abastecimento pertence à sua CI
O software que distribui é o que o seu build de CI produziu, a partir do que descarregou naquele momento. Esse build é o único sítio onde pode ver o que entrou, decidir o que pode entrar e registar o que entrou na versão.
Atualizado a
What software supply chain security means
A definição de trabalho da palestra: o seu software é o seu próprio código mais tudo aquilo de que depende, e a cadeia de abastecimento é cada passo que leva essas partes a uma versão.
Petteri Pulkkinen e Erika Marttinen em Kubernetes Community Days Helsinki 2026, de 2:35 a 4:28 de SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.
O seu build de produção não é o build do seu portátil
A maioria das equipas parte do princípio de que o código que testou localmente é o código que é distribuído. O código-fonte é o mesmo, mas o software muitas vezes não é. Um build é o código-fonte mais tudo o que obtém e tudo o que o rodeia no momento em que é executado, e muito pouco disso é fixo.
As dependências não fixadas resolvem-se de forma diferente
Os intervalos de dependências são a norma. No npm, ^1.0.4 aceita qualquer versão 1.x posterior, pelo que o mesmo package.json instala versões diferentes em dias diferentes. Um lockfile fixa-as, mas apenas se for feito commit dele e o build o respeitar: npm ci falha quando o lockfile e package.json não coincidem, enquanto npm install pode atualizar o lockfile sem aviso. Muitos projetos nem sequer fazem commit de um. O Express 5.2.1, uma framework web amplamente usada, não o faz.
Mesmo uma versão fixada é um nome, não um ficheiro. A documentação do pip explica que fixar a versão, por si só, não impede que um índice de pacotes sirva ficheiros diferentes para a mesma versão, e é por isso que oferece um modo de verificação de hashes.
O tempo altera as entradas
Os registos de pacotes mudam entre builds. São publicadas novas versões, as antigas são retiradas, e um intervalo que se resolveu em segurança na segunda-feira pode apanhar uma versão comprometida na terça-feira. As tags de contentores também mudam: a própria documentação do Docker avisa que as tags de imagem são mutáveis e que um editor pode atualizar uma tag para apontar para uma nova imagem, pelo que FROM node:20 não é a mesma imagem base de um mês para o outro, a menos que a fixe por digest.
O tempo também acaba dentro do resultado. O projeto Reproducible Builds aponta os carimbos temporais como a maior fonte de problemas de reprodutibilidade, porque muitas ferramentas gravam a data e a hora atuais naquilo que compilam.
O ambiente é diferente
- Sistema operativo e arquitetura. Um portátil com macOS e ARM e um runner de CI com Linux e x86-64 instalam binários pré-compilados diferentes para o mesmo pacote. Muitas ferramentas npm são hoje distribuídas como pacotes específicos de cada plataforma que encapsulam um binário compilado.
- Toolchains. As versões de compiladores, runtimes e gestores de pacotes divergem entre máquinas, a menos que todas sejam fixadas.
- Caches. A sua máquina e a sua CI restauram caches diferentes, criadas em momentos diferentes a partir de resoluções diferentes.
- Scripts de instalação e passos de build. Os hooks de pós-instalação, as setup actions e os scripts de build descarregam ferramentas e dados durante o build. Nada disso aparece num manifesto.
- Configuração. As variáveis de ambiente, as flags de build e os segredos existem na CI e em mais lado nenhum.
O projeto Reproducible Builds define um build reprodutível como aquele em que, com o mesmo código-fonte, o mesmo ambiente de build e as mesmas instruções de build, qualquer pessoa consegue recriar cópias idênticas, bit a bit, de todos os artefactos especificados. Essa definição mostra quanto tem de se manter constante. Os builds da maioria das equipas não chegam lá, e os que chegam exigiram muito trabalho. Até lá chegar, o único relato fiável do que foi distribuído é aquele que foi registado enquanto o build distribuído estava em execução.
A software supply chain, walked end to end
Petteri Pulkkinen e Erika Marttinen em Kubernetes Community Days Helsinki 2026, de 15:20 a 16:38 de SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.
Onde pode verificar, e o que cada local consegue ver
As verificações de segurança podem ser executadas em quatro locais. Cada um tem a sua função, mas só um deles vê o build que realmente produziu a sua versão.
| Funcionalidade | No build de CI | Máquina do programador | Análise do repositório | Análise do artefacto |
|---|---|---|---|---|
| Vê as versões que a produção realmente recebeu | Registadas à medida que são obtidas | Uma instalação diferente | Só se um lockfile as fixar | O que conseguir reconhecer |
| Vê pacotes transitivos e restaurados de caches | A sua própria cache, não a da CI | Apenas o lockfile | ||
| Vê o que os scripts de instalação descarregam | ||||
| Consegue travar uma ligação de saída maliciosa | Política de egress no runner | |||
| Deteta problemas antes do push do código | Em pull requests |
- Incluído
- Em parte
- Não incluído
Uma análise do repositório reporta o que o projeto declara. Uma análise do artefacto final reporta o que consegue reconhecer dentro dele. Nenhuma viu o build acontecer. O Express 5.2.1 não faz commit de nenhum lockfile, pelo que um scanner apontado para um checkout limpo não tem nenhuma das dependências npm do projeto para resolver e reporta o que mais reconhecer. Aponte a mesma ferramenta para uma cópia instalada do mesmo repositório e uma flag de cataloger volta a mudar a resposta. O resultado depende do que tiver sido instalado antes da análise, e é exatamente essa a parte que uma análise não controla. A página sobre SBOM durante o build explica porque as análises discordam e o que muda ao registar o build.
O pipeline é, por si só, um alvo
A CI é onde o código-fonte, as dependências e os segredos se encontram, o que a torna um alvo apetecível.
- tj-actions/changed-files (2025). Uma GitHub Action amplamente usada foi comprometida e imprimiu segredos de CI nos logs de build.
- Codecov Bash Uploader (2021). Um script modificado, executado na CI dos clientes, enviou variáveis de ambiente para o servidor de um atacante.
- O worm npm Shai-Hulud (2025). Pacotes comprometidos roubaram credenciais durante a instalação e usaram-nas para publicar mais pacotes comprometidos.
- xz utils (2024). Uma backdoor foi escondida em tarballs de lançamento e no próprio processo de build, não no código-fonte visível.
Cada um destes casos executou código durante um build ou uma instalação. Uma análise do repositório feita antes, ou uma análise do artefacto feita depois, não teria visto o que o processo de build fez. Os controlos que vigiam e limitam aquilo a que um job pode chegar têm de estar onde o job é executado. Isto vale também para aplicações internas e de baixo perfil: ataques como estes visam o pipeline e os pacotes que todas as aplicações partilham, não o que uma aplicação faz. Consulte segurança da cadeia de abastecimento para software interno e de baixo risco.
Mais código, mais dependências, menos pessoas a lê-los
Os agentes de programação com IA escrevem e alteram código mais depressa do que as equipas conseguem rever cada linha, e acrescentam dependências pelo caminho. Também indicam pacotes que não existem: um estudo da USENIX Security 2025 sobre 576.000 amostras de código gerado encontrou percentagens de pacotes alucinados de pelo menos 5,2% nos modelos comerciais e de 21,7% nos modelos open source. Um atacante que registe um desses nomes vê o seu pacote instalado pelo build seguinte que confie nele.
Cada alteração, seja quem for ou o que for que a tenha escrito, passa pelo build a caminho da produção. Isso faz do build o único ponto de controlo que não depende de alguém ter olhado.
As evidências têm de descrever o que foi distribuído
Os regulamentos e os clientes pedem provas, não intenções. O Cyber Resilience Act da UE pede aos fabricantes que identifiquem e documentem os componentes dos seus produtos e que tratem as respetivas vulnerabilidades durante o período de suporte do produto. Uma SBOM gerada a partir de um manifesto descreve o que o projeto pediu. Uma SBOM registada a partir do build descreve o que entrou na versão pela qual é responsável. Quando é publicada uma nova vulnerabilidade, a segunda diz-lhe que versões são afetadas. Leia o que o CRA exige.
O que deve significar "na CI"
Executar um scanner como passo de CI é um começo, mas continua a olhar para ficheiros depois de estes chegarem. Estar "na CI", feito como deve ser, significa:
- Registar, não deduzir. Capture cada pacote e transferência que o job realmente obtém, incluindo as dependências transitivas e tudo o que for restaurado de uma cache.
- Dizer quão completo é o registo. Uma SBOM deve indicar se cobre tudo o que o job obteve, e não apenas listar o que encontrou.
- Controlar o egress. Decida a que hosts um job pode chegar e trave o resto antes que uma dependência comprometida consiga comunicar com o exterior.
- Continuar a vigiar depois do lançamento. Volte a verificar o que foi distribuído à medida que surgem novas vulnerabilidades e transforme as conclusões em correções.
É isto que o CRACI faz. É um runner para os seus jobs de GitHub Actions, pelo que regista o que cada build traz, aplica a política de egress e monitoriza o que distribuiu. Para migrar um workflow, basta uma linha: runs-on: craci. Consulte como funciona o CRACI.
O que a CI não substitui
Colocar a segurança da cadeia de abastecimento no build não torna opcionais as outras camadas.
- As máquinas dos programadores continuam a guardar credenciais e a executar scripts de instalação. Proteja-as também; um portátil comprometido pode fazer push de código antes de qualquer build ser executado.
- A revisão de código e a análise estática encontram falhas no seu próprio código, o que um registo de dependências não faz.
- A fixação de versões, os lockfiles e os digests continuam a ser boas práticas. Reduzem a diferença entre builds; registar o build diz-lhe o que aconteceu de qualquer forma.
O build não é o único sítio onde verificar. É o único sítio que vê o software que realmente distribui.
Veja o CRACI no seu próprio pipeline
Marque uma demo e analisaremos consigo os seus builds, as suas SBOM e as suas evidências de conformidade.
Marcar demo