SBOM
SBOM de imagens Docker: como gerar uma e o que lhe escapa
Pode obter uma SBOM de uma imagem Docker com um único comando, durante o build com o BuildKit ou depois com o Docker Scout ou o Syft. Cada um lê os metadados de pacotes que encontra na imagem. É o registo certo do que a imagem contém, até onde os metadados chegam. Não é um registo de como a imagem foi construída.
Atualizado a
Como gerar uma SBOM para uma imagem Docker
Há três formas comuns. O BuildKit pode escrever a SBOM enquanto constrói a imagem e anexá-la à imagem como atestação. O Docker Scout e o Syft geram uma a partir de uma imagem que já existe, localmente ou num registo.
Durante o build, com o BuildKit
Acrescente --sbom=true, ou a sua forma longa --attest type=sbom, a docker buildx build. O BuildKit executa o seu plugin de scanner Syft sobre o resultado e anexa a SBOM à imagem como um documento SPDX JSON. Faça o build com o exporter local para ver a SBOM antes de fazer push de qualquer coisa:
# Build the image, attach an SBOM attestation and push it
docker buildx build --sbom=true -t registry.example.com/app:1.0 --push .
# The long form of the same option
docker buildx build --attest type=sbom -t registry.example.com/app:1.0 --push .
# Check the SBOM before pushing: write the build result to ./out
docker buildx build --sbom=true --output type=local,dest=out .
# out/sbom.spdx.json is the SBOM Ler a SBOM anexada a uma imagem
docker buildx imagetools inspect lê a atestação a partir do registo. Tudo o que diz respeito à SBOM está em .SBOM no respetivo template Go:
# Print the SPDX document attached to the image
docker buildx imagetools inspect registry.example.com/app:1.0 \
--format "{{ json .SBOM.SPDX }}"
# List each package and its version
docker buildx imagetools inspect registry.example.com/app:1.0 \
--format "{{ range .SBOM.SPDX.packages }}{{ .name }}@{{ .versionInfo }}{{ println }}{{ end }}" A partir de uma imagem existente, com o Docker Scout
docker scout sbom usa a atestação SBOM da imagem quando existe uma. Quando não existe, indexa ele próprio o conteúdo da imagem. Imprime JSON por defeito e escreve para um ficheiro com --output:
# List the packages in an image
docker scout sbom --format list registry.example.com/app:1.0
# Write an SPDX or CycloneDX SBOM to a file
docker scout sbom --format spdx --output app.spdx.json registry.example.com/app:1.0
docker scout sbom --format cyclonedx --output app.cdx.json registry.example.com/app:1.0 A partir de uma imagem existente, com o Syft
O Syft é o scanner open source em que assenta o plugin do BuildKit. Aponte-o para uma imagem e escolha o formato com -o. Acrescente =file para escrever cada formato no seu próprio ficheiro:
# CycloneDX JSON to the terminal
syft registry.example.com/app:1.0 -o cyclonedx-json
# Both formats, each to its own file
syft registry.example.com/app:1.0 -o spdx-json=app.spdx.json -o cyclonedx-json=app.cdx.json SPDX ou CycloneDX?
As atestações do BuildKit são sempre SPDX. O Docker Scout escreve SPDX ou CycloneDX, e o Syft escreve ambos, entre outros formatos. Ambas as normas listam pacotes, versões, licenças e package URLs, pelo que a escolha depende normalmente da ferramenta que vai ler a SBOM a seguir. Consulte CycloneDX vs SPDX para conhecer as diferenças.
Como um scanner de imagens constrói uma SBOM
Todas estas ferramentas funcionam da mesma forma. Desempacotam as camadas da imagem e leem os metadados de pacotes que encontram: a base de dados de pacotes do sistema operativo e os metadados que os gestores de pacotes de linguagens deixam para trás. Cada pacote que conseguem identificar torna-se uma entrada da SBOM, incluindo os pacotes vindos da imagem base.
Incluir as fases de build e o contexto de build
Por defeito, o BuildKit analisa apenas a fase final. Num build de várias fases, os compiladores, as ferramentas de build e os pacotes usados nas fases anteriores não estão na imagem final, pelo que também não estão na sua SBOM. A documentação de atestações SBOM do Docker descreve dois argumentos de build que alargam a análise. BUILDKIT_SBOM_SCAN_STAGE acrescenta uma fase e BUILDKIT_SBOM_SCAN_CONTEXT acrescenta o contexto de build:
# syntax=docker/dockerfile:1
# Scan the build context as well as the image
ARG BUILDKIT_SBOM_SCAN_CONTEXT=true
FROM golang:1.25 AS build
# Include this build stage in the SBOM
ARG BUILDKIT_SBOM_SCAN_STAGE=true
WORKDIR /src
COPY . .
RUN go build -o /out/app .
FROM scratch
COPY --from=build /out/app /app
ENTRYPOINT ["/app"] Ambos têm de ser declarados com ARG no Dockerfile. Defini-los apenas com --build-arg não tem efeito, embora --build-arg possa substituir um valor declarado no Dockerfile. Com o exporter local, cada fase analisada recebe o seu próprio ficheiro, como sbom-build.spdx.json ao lado de sbom.spdx.json.
O que uma análise continua a não ver
A análise de fases fecha uma lacuna. Mas o scanner continua a ler ficheiros, e parte do que um build usa não deixa nenhum ficheiro para trás, ou nenhum que consiga identificar:
- Ficheiros sem metadados de pacotes. Um binário descarregado com
curl, um tarball desempacotado num passoRUNou código vendorizado copiado para a imagem. Alguns binários incluem informação de build que um scanner consegue ler, como os binários Go; muitos não. - O que o build descarregou e apagou. Um pacote ou instalador que um passo
RUNobtém, usa e remove na mesma camada não deixa nada no sistema de ficheiros para qualquer scanner ler, seja na fase final ou não. - Como as coisas entraram. Uma SBOM resultante de uma análise lista o que lá está. Não diz de que registo ou host veio um pacote, nem que passo o obteve.
- Fases que não marcou. A análise de fases tem de ser ativada, por fase ou globalmente. Uma fase sem o argumento continua a ficar de fora.
- Definições da análise. O que aparece depende de como o scanner é executado. Num projeto, uma única flag do Syft decide se os pacotes npm aparecem sequer no resultado.
Porque é importante
Uma ferramenta de build ou imagem base comprometida afeta o que distribui, mesmo que nunca apareça na imagem final. E um binário sem metadados pode conter uma vulnerabilidade para a qual nenhuma entrada da SBOM aponta. Quando surge um aviso de segurança, precisa de saber o que entrou na construção da imagem, além do que está nela.
Registe também o build
A SBOM da imagem responde ao que está dentro da imagem. Um registo do build responde ao que o build trouxe: as imagens base que obteve e os pacotes que cada passo obteve, incluindo as dependências ocultas que nenhum lockfile lista. O CRACI regista isso enquanto o seu job de GitHub Actions é executado, através de um proxy que reconhece pacotes no runner, e a API devolve SBOM, traços de rede e proveniência do job. Use a SBOM da imagem para o que distribui e o registo do build para saber como foi feito.
Consulte ferramentas de SBOM comparadas, SBOM durante o build e como gerar uma SBOM no GitHub Actions.
SBOM de imagens Docker: perguntas frequentes
Como gero uma SBOM para uma imagem Docker?
Há três formas comuns. Acrescente --sbom=true a docker buildx build e o BuildKit anexa uma SBOM SPDX à imagem. Execute docker scout sbom numa imagem existente. Ou execute o Syft, por exemplo syft IMAGE -o cyclonedx-json. Os três leem os pacotes que encontram na imagem.
O que é um scanner de SBOM?
Uma ferramenta que lê ficheiros, como um diretório de código-fonte, um lockfile ou uma imagem de contentor, e escreve uma SBOM dos pacotes que consegue identificar. O Syft, o Trivy, o Docker Scout e o plugin Syft do BuildKit são scanners de SBOM. Descrevem os ficheiros que têm à frente, não o build que os produziu.
Que formato de SBOM produz o Docker?
As atestações do BuildKit são documentos SPDX JSON anexados à imagem. O Docker Scout pode imprimir uma lista de pacotes ou escrever SPDX ou CycloneDX. O Syft escreve ambos, e outros. Escolha o formato que a ferramenta que consome a SBOM espera.
Como é que um scanner constrói uma SBOM a partir de uma imagem Docker?
Desempacota as camadas da imagem e lê os metadados de pacotes que encontra: a base de dados de pacotes do sistema operativo e os ficheiros de pacotes de linguagens, como os metadados de pacotes npm ou Python instalados. Cada pacote que consegue identificar torna-se uma entrada da SBOM.
Porque é que uma SBOM de imagem pode deixar de fora um componente?
Porque só pode listar o que consegue identificar nos ficheiros que lê. Um binário descarregado com curl não tem metadados de pacotes, um pacote que um passo de build descarregou e apagou não deixa nada para ler, e as fases de build anteriores ficam de fora a menos que ative a análise de fases.
Uma SBOM de imagem continua a ser útil?
Sim. É o registo certo do que está dentro da imagem que distribui, incluindo os pacotes da imagem base. Só não descreve como a imagem foi construída, pelo que deve combiná-la com um registo do build quando isso for importante.
Veja o que o build da sua imagem trouxe
Execute um build de imagem no CRACI e compare o registo das imagens base e dos pacotes obtidos com a SBOM de imagem do seu scanner.
Marcar demo