Mais 123% CVE comunicadas por dia em 2026 do que no ano passado.

Yocto

SBOM e builds Yocto no CRACI

O Yocto consegue escrever uma SBOM em SPDX detalhada para cada imagem. Num build lado a lado, a SBOM registada pelo CRACI tinha todos os componentes da do Yocto, mais 88 que esta não incluía, e um package URL para cada um dos 653 crates Rust que o Yocto lista sem ele, com menos 43% de tempo de build.

Atualizado a

Num build lado a lado: core-image-sato

Componentes listados: mais 10% na SBOM do CRACI

SBOM do CRACI
953
SBOM do Yocto
865

88 componentes que faltam na do Yocto, como pacotes do anfitrião e GitHub Actions; nenhum só na do Yocto

Crates Rust com package URL, para que possam ser verificados quanto a vulnerabilidades

SBOM do CRACI
653
SBOM do Yocto
0

Ambas listam os mesmos 653; a do Yocto apenas pelo nome de ficheiro e pelo URL de descarga

Tempo de build e custo por build, ARM64 com 32 vCPU

CRACI
1 h 29 min $5.68
CRACI + SBOM do Yocto
2 h 36 min $9.96
GitHub + SBOM do Yocto*
5 h 11 min $15.60
43% menos custo: CRACI face a CRACI + SBOM do Yocto
64% menos custo: CRACI face a GitHub + SBOM do Yocto*

*Estimativa para um runner ARM64 de 32 núcleos alojado no GitHub a $0.050 por minuto, com o CRACI cerca de duas vezes mais rápido.

Obtenha a comparação completa ↓

Como gerar uma SBOM com o Yocto

O sistema de build OpenEmbedded escreve SBOM em SPDX através da classe create-spdx. Se está ativa, e que versão de SPDX escreve, depende da versão do Yocto:

  • Kirkstone (4.0): desativada por predefinição. Adicione INHERIT += "create-spdx". SPDX 2.2.
  • Nanbield (4.3): a geração de SBOM fica ativa por predefinição a partir desta versão.
  • Scarthgap (5.0): ativa por predefinição, SPDX 2.2. O SPDX 3.0 está disponível através da classe create-spdx-3.0.
  • Styhead (5.1) e posteriores: ativa por predefinição, SPDX 3.0.

A definição é feita num ficheiro de configuração como conf/local.conf. Numa versão atual, normalmente não há nada a acrescentar; para a desativar, use INHERIT_DISTRO:remove = "create-spdx".

# conf/local.conf

# Kirkstone (4.0): SBOM generation is off by default, so turn it on
INHERIT += "create-spdx"

# Scarthgap (5.0): switch the output from SPDX 2.2 to SPDX 3.0
INHERIT_DISTRO:remove = "create-spdx"
INHERIT_DISTRO:append = " create-spdx-3.0"

# Any release: indented JSON you can read in an editor
SPDX_PRETTY = "1"

Outras variáveis SPDX_ acrescentam detalhe. SPDX_INCLUDE_SOURCES descreve os ficheiros-fonte por trás de cada ferramenta do anfitrião e de cada pacote de destino, o que torna o resultado muito maior. As versões recentes acrescentam opções para a configuração do kernel, as funcionalidades PACKAGECONFIG, informação sobre fornecedores e package URLs para fontes Cargo, Go, PyPI, npm e CPAN.

Onde ficam os ficheiros da SBOM

Faça o build de uma imagem e a SBOM de nível superior aparece junto dela, como IMAGE-MACHINE.spdx.json em tmp/deploy/images/MACHINE/, dentro do diretório de build. Os ficheiros relacionados estão no mesmo diretório e em tmp/deploy/spdx. No Kirkstone, os documentos por receita vêm num arquivo IMAGE-MACHINE.spdx.tar.zst.

bitbake core-image-minimal

# The image SBOM
ls tmp/deploy/images/qemux86-64/core-image-minimal-qemux86-64.spdx.json

# Per-recipe and package documents
ls tmp/deploy/spdx/

# Current releases: an SBOM for one recipe, from its metadata only
bitbake busybox -c create_recipe_sbom

CycloneDX com meta-cyclonedx

O próprio Yocto escreve apenas SPDX. Para CycloneDX, a camada meta-cyclonedx gera uma SBOM a partir do sistema de ficheiros raiz da imagem, e ainda um ficheiro VEX separado com as CVE corrigidas e ignoradas que o sistema de build conhece. Faça checkout do branch da camada correspondente à sua versão, adicione-a às suas camadas e herde a respetiva classe:

# In your sources directory, on the branch for your release
git clone https://github.com/iris-GmbH/meta-cyclonedx.git
cd meta-cyclonedx
git checkout scarthgap

# conf/bblayers.conf
BBLAYERS += "${BSPDIR}/sources/meta-cyclonedx"

# conf/local.conf
INHERIT += "cyclonedx-export"
# Optional: include build-time packages, not only what is in the image
CYCLONEDX_RUNTIME_PACKAGES_ONLY = "0"

Os ficheiros ficam junto à imagem em DEPLOY_DIR_IMAGE, com os sufixos .cyclonedx.bom.json e .cyclonedx.vex.json. A predefinição é CycloneDX 1.6, definida com CYCLONEDX_SPEC_VERSION. Por predefinição, só são incluídos os pacotes de runtime, o que mantém a SBOM pequena mas pode deixar de fora componentes que chegam à imagem sem serem instalados como pacotes.

O que a SBOM do Yocto deixa de fora

A SBOM do Yocto é minuciosa quanto ao que o BitBake constrói. Em SPDX 3, abrange a imagem, todas as receitas, incluindo as nativas usadas no build, as respetivas fontes, os patches aplicados e as vulnerabilidades marcadas como corrigidas. Para core-image-sato, isso deu 1,632 ficheiros separados. Para ver o que fica de fora, fizemos o build da imagem num runner do CRACI, ARM64 nativo com 32 vCPU, e comparámos a SBOM do Yocto com a que o CRACI registou, componente a componente, depois de normalizar os nomes em todos esses ficheiros.

Dos 953 componentes da SBOM do CRACI, 865 estavam também na do Yocto. Nenhum estava apenas na do Yocto. As diferenças estão naquilo que o Yocto não consegue ver e na forma como identifica o que lista.

Crates Rust sem package URL

Ambas as SBOM contêm as mesmas 653 versões de 559 crates Rust, como cairo-rs e zune-jpeg, que o librsvg compila. O Yocto lista cada um apenas como um ficheiro .crate e um URL de descarga de crates.io, dentro da receita que o utiliza. Nenhum tem um package URL pkg:cargo. O CRACI regista cada crate com um.

É isso que determina se os pode monitorizar quanto a vulnerabilidades. A correspondência de vulnerabilidades funciona com package URLs: um aviso de segurança sobre um crate identifica-o como pkg:cargo/..., e um nome de ficheiro na lista de fontes de outra receita não dá às ferramentas de SBOM e de vulnerabilidades nada com que o cruzar. Só com a SBOM do Yocto, um crate vulnerável na sua imagem passa sem ser reportado.

Com a do CRACI, cada crate é cruzado com os avisos de segurança, cada pacote do build mostra o seu estado de vulnerabilidade e o CRACI continua a reavaliar a SBOM à medida que são publicados novos avisos, muito depois de o build terminar.

O que só o CRACI encontrou

Os 88 componentes que faltavam na SBOM do Yocto vieram de fora dos metadados do BitBake:

  • 23 pacotes do anfitrião instalados na máquina de build, como o cpio 2.15 do Ubuntu, libc6, locales e python3-jinja2. O BitBake é executado com eles, e a SBOM do Yocto não os lista.
  • 10 fontes do GitHub, incluindo patchelf, btrfs-progs e a GitHub Action actions/upload-artifact, fixadas no commit que o workflow executou
  • Outras fontes e ferramentas obtidas durante o build, como pseudo-prebuilt, tzdata e ferramentas de build Python como hatchling e setuptools_scm

Nenhum destes está instalado na imagem, mas todos estão no caminho crítico do build: uma ferramenta do anfitrião ou uma Action comprometida pode comprometer a sua imagem sem nunca fazer parte dela. O CRACI lista-os porque vê o tráfego que entra no build.

Quanto custa a SBOM integrada

A geração de SBOM do Yocto não é gratuita. No mesmo runner de 32 vCPU, o build com ela demorou 155 min 40 s e escreveu a SBOM em 1,632 ficheiros SPDX separados. O build sem ela, com o CRACI a registar, demorou 88 min 48 s. À tarifa do CRACI de $0.002 por vCPU-minuto, isso dá cerca de $9.96 contra $5.68 por build, antes de contar o tempo que a sua equipa passa à espera.

A diferença é maior face aos runners alojados no GitHub. O CRACI executa builds cerca de duas vezes mais depressa, graças a hardware mais rápido, filas de espera mais curtas e cache, pelo que o mesmo build com a SBOM do Yocto num runner ARM64 de 32 núcleos alojado no GitHub demoraria cerca de 5 h 11 min. A $0.050 por minuto, isso dá $15.60. O build no CRACI custa $5.68: menos 64%, ou cerca de 2,7 vezes mais barato. Preços de tabela do GitHub em setembro de 2026; os minutos incluídos não abrangem runners maiores.

O resultado em SPDX do Yocto inclui elementos que o CRACI não regista, como os patches que uma receita aplica e as CVE que marca como corrigidas. Se o seu processo depende deles, mantenha o create-spdx ativo e use a SBOM do CRACI em paralelo. Caso contrário, a SBOM do CRACI abrange, por si só, todos os componentes da do Yocto, e mais.

Porque é que isto importa para a segurança da cadeia de abastecimento

O que entra num build determina o que sai dele, esteja ou não instalado na imagem. Os atacantes sabem-no, e é pelo build que os ataques recentes à cadeia de abastecimento têm entrado:

  • Os ataques escondem-se no build. O backdoor do xz utils (CVE-2024-3094) estava nas versões 5.6.0 e 5.6.1. O seu gatilho estava nos tarballs de lançamento e não no repositório Git, e o código malicioso entrou na biblioteca durante o build. Ler o código-fonte não o revelava; saber exatamente que tarball o build obteve, sim.
  • As dependências de CI também são alvos. Em março de 2025, a CISA reportou que todas as versões da GitHub Action tj-actions/changed-files estiveram comprometidas durante três dias. Uma Action é executada dentro do seu job de build, e é por isso que o CRACI lista as que o seu workflow usou, fixadas no commit que foi executado.
  • Os crates Rust desaparecem dentro dos binários. O Cargo compila os crates nos programas que os usam, pelo que um crate vulnerável é distribuído dentro da imagem sem nunca aparecer como pacote. Se a SBOM o lista apenas como nome de ficheiro, as ferramentas de vulnerabilidades também não o conseguem cruzar. Analisar depois o binário final obriga a adivinhar o que entrou; registar o build, não.
  • Não é possível responder ao que não se vê. Quando surge um aviso de segurança sobre um crate ou uma ferramenta de build, precisa de saber que builds o usaram. O CRACI guarda a SBOM de cada build e mostra que builds continham a dependência vulnerável, direta ou transitiva, para que saiba durante que período esteve afetado. Isso só funciona quando cada componente tem um package URL com que fazer a correspondência.
  • Um build só deve chegar àquilo de que precisa. A política de egress do CRACI bloqueia ligações a anfitriões de que o build não precisa, pelo que uma dependência comprometida que tente enviar os seus segredos para o servidor de um atacante é travada, mesmo num ataque que ninguém viu antes.

Os clientes e regulamentos como o Cyber Resilience Act também pedem aos fabricantes de dispositivos ligados que saibam o que entra nos seus produtos. Uma SBOM que abrange todo o build é uma evidência que resiste ao escrutínio quando a pedem.

Obtenha a comparação completa

As listas de componentes por trás destes números, ambas as SBOM e a forma como as gerámos e comparámos.

  • Os 88 componentes que só o CRACI encontrou, e os 865 que ambas as SBOM listavam
  • Como cada SBOM identifica as 653 versões de crates Rust
  • Os dois ficheiros SBOM: o CycloneDX do CRACI e o SPDX do Yocto
  • A configuração do build, o tamanho do runner e os tempos

Porque é que os builds Yocto são difíceis de executar em CI

O build de uma imagem completa compila uma toolchain, um kernel e centenas de pacotes a partir do código-fonte. Nos runners padrão de 2 núcleos que a maioria dos serviços de CI oferece, isso pode demorar horas, pelo que muitas equipas de sistemas embebidos mantêm um servidor de build dedicado debaixo de uma secretária ou num rack, e esse servidor torna-se mais uma máquina para atualizar, fazer cópias de segurança e explicar a um auditor.

Um build Yocto também descarrega muita coisa: tarballs de código-fonte, repositórios Git e patches de projetos upstream e mirrors. São essas descargas que a sua SBOM tem de contemplar, e que regulamentos como o Cyber Resilience Act pedem aos fabricantes de dispositivos ligados que conheçam e acompanhem.

O que o CRACI dá a um build Yocto

Runners dimensionados para o BitBake

Os runners do CRACI escalam de 1 a 32 unidades de computação, em que cada unidade corresponde a 1 vCPU e 3 GB de RAM. Um build Yocto pode pedir o tamanho maior, 32 vCPU e 96 GB de RAM, a partir do próprio workflow. Os jobs são executados em máquinas virtuais isoladas e as execuções continuam a aparecer no GitHub como qualquer outro job de Actions.

Os minutos são medidos ao segundo e faturados por vCPU-minuto, pelo que um runner grande custa mais por minuto e termina mais cedo. Consulte os preços para as tarifas atuais.

Acesso à rede decidido por si

O BitBake já consegue restringir o seu fetcher a uma lista de anfitriões com BB_ALLOWED_NETWORKS. O CRACI acrescenta um segundo controlo no runner: uma política de egress verificada antes do início do job e que falha em modo fechado, para que uma receita, um script ou uma ferramenta comprometida que contorne o fetcher continue sem conseguir chegar a um anfitrião que não autorizou. O CRACI alerta-o para violações da política.

Um registo do que o build obteve

O CRACI observa o tráfego que um job envia para os anfitriões de pacotes e de fontes e regista-o como evidência do build. Num build Yocto, isso significa um registo independente das fontes que efetivamente chegaram pela rede, ao lado da SBOM que o próprio Yocto escreve.

Um workflow mínimo

O exemplo Yocto na documentação do CRACI faz o build de core-image-sato para qemux86-64. As partes que importam para o CRACI são o tamanho do runner e uma configuração do fetcher que usa o mirror oficial de fontes do Yocto:

jobs:
  build:
    runs-on: craci
    steps:
      - uses: cracicorp/setup@v1
        with:
          size: "32"
      # install the host packages from the Yocto quick start, then:
      - run: |
          echo 'SOURCE_MIRROR_URL = "https://downloads.yoctoproject.org/mirror/sources/"' >> conf/local.conf
          echo 'BB_ALLOWED_NETWORKS = "downloads.yoctoproject.org"' >> conf/local.conf
          bitbake core-image-sato

O guia da documentação tem o workflow completo, incluindo as dependências do anfitrião e a configuração de locale, e a referência de configuração do runner lista todas as opções de setup.

O que deve saber

  • Os builds são executados nos runners geridos do CRACI em infraestrutura europeia, a partir do GitHub Actions. Os runners alojados pelo cliente e outros sistemas de CI estão no roadmap.
  • Aponte o BitBake para mirrors que o CRACI consiga ver, como o mirror oficial de fontes do Yocto, e não para anfitriões arbitrários. O guia da documentação mostra uma configuração funcional.
  • Manter o diretório de descargas e a cache de shared state entre execuções é o que torna rápidos os builds repetidos.
  • Os runners ARM64 nativos estão disponíveis à mesma tarifa que os x86-64.

Desenvolve dispositivos ligados para o mercado da UE? Leia o que o CRA exige e como o CRACI funciona para IoT industrial e eletrónica de consumo. Está a comparar ferramentas de SBOM para Yocto? Consulte CRACI vs Timesys Vigiles.

SBOM do Yocto e CRACI: perguntas frequentes

O Yocto gera uma SBOM?

Sim. O sistema de build OpenEmbedded gera por predefinição uma SBOM em SPDX desde o Yocto 4.3 (Nanbield), através da classe create-spdx. Para uma imagem, escreve IMAGE-MACHINE.spdx.json em tmp/deploy/images/MACHINE/, abrangendo componentes, licenças, dependências, fontes, patches aplicados e vulnerabilidades corrigidas. No Kirkstone (4.0), adicione INHERIT += "create-spdx" para a ativar.

Que versão de SPDX produz o Yocto?

SPDX 3.0 por predefinição desde o Yocto 5.1 (Styhead), que substituiu a 2.2 como predefinição. O Scarthgap (5.0) produz SPDX 2.2 por predefinição e pode passar para 3.0 com a classe create-spdx-3.0.

Como obtenho uma SBOM em CycloneDX a partir do Yocto?

Adicione a camada meta-cyclonedx no branch correspondente à sua versão e herde cyclonedx-export em local.conf. Esta escreve uma SBOM .cyclonedx.bom.json e um ficheiro .cyclonedx.vex.json junto à imagem, em CycloneDX 1.6 por predefinição.

O que falta na SBOM do Yocto?

Num build lado a lado de core-image-sato, a SBOM registada pelo CRACI tinha os 865 componentes da SBOM do Yocto e mais 88: pacotes do anfitrião na máquina de build, como o cpio do Ubuntu, fontes e Actions do GitHub, e outras fontes obtidas durante o build. O Yocto lista também as suas 653 versões de crates Rust apenas pelo nome de ficheiro e pelo URL de descarga, sem package URL, de que a correspondência de vulnerabilidades depende.

Posso monitorizar vulnerabilidades num build Yocto?

Sim, com o CRACI. A correspondência de vulnerabilidades funciona com package URLs, e a SBOM integrada do Yocto lista os crates Rust apenas pelo nome de ficheiro e pelo URL de descarga, pelo que não é possível cruzá-los. O CRACI regista os crates Rust e os pacotes da máquina de build com os package URLs com que os avisos de segurança são publicados (pkg:cargo, pkg:deb), incluindo as 653 versões de crates de core-image-sato. Mostra o estado de vulnerabilidade de cada pacote e continua a reavaliar a SBOM à medida que são publicados novos avisos.

O CRACI pode substituir a SBOM do Yocto?

Em termos de cobertura da cadeia de abastecimento, sim. Na mesma comparação, a SBOM do CRACI tinha todos os componentes da SBOM integrada do Yocto, mais 88 e um package URL para cada crate Rust, e o build sem a geração de SBOM do Yocto demorou menos 43%. O resultado em SPDX do Yocto continua a incluir metadados das receitas que o CRACI não regista, como os patches aplicados e as CVE que uma receita marca como corrigidas. Se depende deles, mantenha o create-spdx ativo.

Um runner do CRACI aguenta um build completo de uma imagem Yocto?

Os runners do CRACI vão até 32 vCPU e 96 GB de RAM, definidos a partir do workflow. A documentação do CRACI inclui um exemplo Yocto que faz o build de core-image-sato no tamanho maior.

Que CI utiliza um build Yocto no CRACI?

GitHub Actions. O seu workflow é executado nos runners geridos do CRACI e as execuções aparecem no GitHub como qualquer outro job de Actions. Outros sistemas de CI e runners alojados pelo cliente estão no roadmap.

Traga um build Yocto para a demo

Marque uma demo e executaremos um dos seus builds BitBake num runner do CRACI e analisaremos consigo o que obteve.

Marcar demo