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

Yocto

Porque os scanners de SBOM não veem o que está nos builds Yocto

Os scanners leem um resultado, como um sistema de ficheiros, um binário ou um manifesto, e deduzem o que entrou nele. Uma imagem Yocto esconde a maior parte disso: as bibliotecas estáticas e os crates Rust são compilados para dentro dos binários, os patches das receitas alteram código sem alterar os números de versão, a configuração do kernel decide que código chega sequer a existir e as ferramentas do anfitrião de build nunca chegam à imagem. A alternativa é registar o build e manter os metadados de patches e CVE do próprio Yocto.

Atualizado a

Num minuto

  • Anfitrião de build: as ferramentas da máquina de build moldam a imagem e nunca aparecem nela. Um scanner da imagem não as consegue ver.
  • Obtenção: o BitBake descarrega fontes, crates Rust, módulos Go e ferramentas. Um scanner vê apenas o que sobrevive até à imagem.
  • Receitas e patches: uma receita mantém a versão upstream e aplica patches de segurança por cima. Um scanner que compara versões reporta CVE que já estão corrigidas.
  • Código compilado: bibliotecas estáticas, crates e a configuração do kernel acabam dentro dos binários. Um scanner vê um ficheiro onde entraram dezenas de componentes.
  • Imagem: as imagens de produção deixam muitas vezes de fora a base de dados de pacotes. O scanner fica então sem lista para ler e reporta pouco ou nada.

Em que difere um build Yocto do que os scanners esperam

Um build Yocto não é uma instalação feita por um gestor de pacotes. A maior parte do que acaba no dispositivo é decidida no momento do build, dentro do BitBake, em cinco camadas. Os scanners olham para uma camada depois do facto e têm de adivinhar o resto.

As cinco camadas de um build Yocto e onde cada ferramenta olha Cinco camadas sobrepostas: o anfitrião de build, a obtenção, as receitas e os patches, o código compilado e a imagem. O registo do build vê o anfitrião, as obtenções e as fontes enquanto o build decorre. O create-spdx do Yocto descreve receitas, patches e o estado das CVE. Os scanners de imagens e a análise de binários olham apenas para o resultado, a imagem. 1. Build host HOSTTOOLS, -native and -cross recipes 2. Fetch SRC_URI into DL_DIR, crate://, Go modules, mirrors 3. Recipes and patches PV, patches with CVE: tags, CVE_STATUS 4. Compiled code static libraries, crates, kernel config 5. Image root filesystem, package database if kept Build recording host, fetch, sources create-spdx recipes, patches, CVEs Image and binary scanners look at the output only Each tool sees the layers its box spans.
Cada tipo de ferramenta vê uma parte do build. Nenhuma vê as cinco camadas, e por isso a escolha certa depende da camada de que precisa.

1. O anfitrião de build

O BitBake corre com ferramentas da máquina de build. A variável HOSTTOOLS lista as ferramentas do anfitrião de build que as tarefas de build podem chamar, e o sistema de build cria ligações simbólicas para elas em ${TMPDIR}/hosttools. O BitBake também constrói as suas próprias ferramentas através de receitas -native e -cross. As ferramentas do anfitrião influenciam a imagem e, por conceção, não fazem parte dela.

2. Obtenção

As receitas indicam as suas fontes em SRC_URI, e o fetcher descarrega-as para DL_DIR. Procura primeiro em DL_DIR, depois em PREMIRRORS, depois upstream e por fim em MIRRORS. Os crates Rust chegam através do fetcher crate://, listados num ficheiro -crates.inc que o cargo-update-recipe-crates gera a partir de Cargo.lock. Os módulos Go chegam através da classe go-mod ou são incluídos com go-vendor. BB_NO_NETWORK e BB_ALLOWED_NETWORKS controlam o que o fetcher pode alcançar.

3. Receitas e patches

Cada receita fixa uma versão upstream em PV e aplica patches por cima. Um patch com uma linha CVE: no cabeçalho marca essa CVE como corrigida. O número de versão continua a ser o upstream, pelo que a receita pode estar corrigida enquanto a sua versão diz o contrário.

4. Código compilado

As bibliotecas estáticas (os pacotes -staticdev), os crates Rust e os módulos Go acabam dentro dos binários que os utilizam. O kernel e os seus módulos são construídos a partir de uma configuração específica do produto, pelo que duas plataformas com a mesma versão do kernel contêm código diferente.

5. A imagem

O sistema de ficheiros raiz. A funcionalidade de imagem package-management instala as ferramentas de gestão de pacotes e preserva a base de dados do gestor de pacotes. Sem ela, os ficheiros de dados do gestor de pacotes são apagados do sistema de ficheiros raiz, o que é comum nas imagens de produção.

A cache shared state (sstate)

O BitBake pode restaurar o resultado de uma tarefa a partir da cache shared state (estado partilhado) em vez de a executar. O manual de visão geral do Yocto di-lo claramente: se os objetos pré-construídos estiverem disponíveis, o compilador não é necessário, "assim, o compilador nem sequer é descarregado". As tarefas restauradas a partir do sstate saltam a obtenção, a compilação e a instalação, o que importa para qualquer ferramenta que dependa de observar esses passos. Mais sobre isto na secção sobre caches, abaixo.

Porque os scanners de imagens e de sistemas de ficheiros não veem a maior parte

  • Sem base de dados de pacotes. Uma imagem de produção construída sem package-management não dá ao scanner nenhuma lista para ler, pelo que este recorre a heurísticas sobre ficheiros ou não reporta quase nada. O resultado parece completo e está quase vazio.
  • Código estático e incluído. Uma biblioteca estática ou um crate compilado para /usr/bin/foo não deixa nenhum registo de pacote. O librsvg é um exemplo: a receita atual do oe-core lista mais de 350 crates Rust, e no dispositivo é uma única biblioteca partilhada.
  • Anfitrião de build e ferramentas obtidas. Nunca estão na imagem, e por isso nunca numa análise da imagem, embora uma ferramenta do anfitrião ou uma GitHub Action comprometida possa comprometer a imagem. A backdoor do xz utils (CVE-2024-3094) entrou na biblioteca enquanto esta era construída, a partir dos tarballs de release e não do repositório Git. 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.
  • Patches aplicados. A imagem indica openssl numa versão upstream. A receita aplicou a correção de uma CVE que afeta essa versão e marcou o patch com CVE:. Uma correspondência por intervalo de versões assinala-a na mesma. É a forma Yocto do problema dos backports das distribuições, e uma das principais fontes do ruído tratado em como reduzir o ruído de vulnerabilidades.

O resultado é uma mistura de componentes em falta e de resultados errados, e nada no resultado indica qual é qual. O mesmo argumento aplica-se aos contentores nas SBOM de imagens Docker e aos projetos de linguagens nos geradores de SBOM open source.

Porque a análise de binários de firmware tem de adivinhar

A análise de binários compara strings, símbolos e assinaturas de código no firmware extraído com componentes conhecidos e depois deduz as versões. Onde o binário traz provas claras, isso funciona. Numa imagem Yocto, muitas vezes tem de adivinhar:

  • binários stripped sem strings de versão;
  • código ligado estaticamente, onde as fronteiras entre bibliotecas desapareceram;
  • Rust compilado, onde as fronteiras entre crates desaparecem num único executável;
  • patches com backport, que são invisíveis num número de versão;
  • código do kernel que a configuração incluiu ou excluiu da compilação.

A análise de binários é a ferramenta certa para firmware que não construiu: blobs de fornecedores, módulos comprados, um dispositivo que está a avaliar. Se não tem o build, analisar o binário é a única opção. A regra de decisão é simples: se o constrói, registe-o; se apenas o recebe, analise-o e peça ao fornecedor uma SBOM do build dele.

O que as ferramentas de SBOM e CVE do próprio Yocto fazem bem

O trabalho do Yocto Project em SBOM é boa engenharia, e sabe coisas que nenhuma ferramenta externa consegue saber. A sua documentação diz que a SBOM é "uma descrição de todos os componentes que utilizou, das suas licenças, das suas dependências, das suas fontes, das alterações que lhes foram aplicadas e das vulnerabilidades conhecidas que foram corrigidas".

create-spdx por versão

  • 4.3 (Nanbield): a geração de SPDX está ativa por predefinição.
  • 5.1 (Styhead): SPDX 3.0 por predefinição em vez de 2.2, e uma classe vex que dá às ferramentas de CVE externas a informação de que precisam.
  • 5.3 (Whinlatter): SPDX_INCLUDE_COMPILED_SOURCES, que inclui apenas as fontes usadas para compilar.
  • 6.0 (Wrynose, suporte de longo prazo): SPDX 2.2 removido; SPDX_INCLUDE_KERNEL_CONFIG e SPDX_INCLUDE_PACKAGECONFIG adicionados; as receitas construídas com as classes Cargo, Go, PyPI, npm e CPAN recebem um package URL do ecossistema.

A SBOM abrange o que o BitBake constrói, incluindo as ferramentas nativas que constrói para o anfitrião. É exaustiva em relação a tudo o que tem uma receita.

Estado das CVE como VEX dentro da SBOM

Em SPDX 3, o sistema de build escreve o estado das CVE de cada receita como relações VEX: uma CVE corrigida passa a "fixed", ligada aos ficheiros de patch; uma não corrigida, "affected"; uma ignorada, "not affected", com o motivo como declaração de impacto. SPDX_INCLUDE_VEX define quanto é incluído: none, current (a predefinição, vulnerabilidades ainda não corrigidas na fonte upstream) ou all.

CVE_STATUS e a marcação do patch

CVE_STATUS regista uma decisão por CVE, como um motivo e uma descrição opcional. Os motivos correspondem a corrigida (backported-patch, cpe-stable-backport, fixed-version e outros), não corrigida (vulnerable-investigating) e ignorada (cpe-incorrect, disputed, not-applicable-config, not-applicable-platform, upstream-wontfix). CVE_STATUS_GROUPS aplica uma decisão a um grupo de CVE, e CVE_PRODUCT define o nome do produto usado na correspondência.

# In a recipe or .bbappend
CVE_STATUS[CVE-2020-15523] = "not-applicable-platform: Issue only applies on Windows"

# In the header of a patch file
CVE: CVE-2022-3341
Upstream-Status: Backport [link to the upstream commit]

De cve-check a sbom-cve-check

O cve-check comparava os nomes das receitas (CVE_PRODUCT) e as versões com os dados de vulnerabilidades. As notas de lançamento da 5.2 avisam que, desde o início de 2024, os responsáveis pela NVD deixaram de anotar muitas CVE com os CPE afetados, pelo que "os relatórios de CVE atuais podem parecer bons, mas a realidade é que algumas vulnerabilidades simplesmente não são reportadas". A 5.2 tornou também o feed FKIE a predefinição em vez da NVD. O Yocto 6.0 removeu o cve-check e substituiu-o pela classe sbom-cve-check, que executa o sbom-cve-check da Bootlin sobre o resultado SPDX. Da 5.0 à 5.3 continua a ter o cve-check; trate-o como legado.

Onde a SBOM do Yocto termina

O que o Yocto não consegue ver é tudo o que está fora dos metadados do BitBake. Construímos core-image-sato duas vezes num runner ARM64 nativo com 32 vCPUs, uma vez com a geração de SBOM do Yocto e outra sem ela, e comparámos a SBOM SPDX 3.0.1 do Yocto, escrita em 1.632 ficheiros, com a SBOM CycloneDX que o CRACI registou:

  • Componentes. A SBOM registada pelo CRACI tinha todos os componentes da SBOM do Yocto e mais 88 que esta não tinha: 23 pacotes do anfitrião na máquina de build (como o cpio do Ubuntu), 10 fontes do GitHub, incluindo a GitHub Action actions/upload-artifact, e 55 outras fontes e ferramentas obtidas durante o build.
  • Crates Rust. Ambas listavam as mesmas 653 versões de crates Rust. Na versão que construímos, a SBOM do Yocto listava-as apenas como ficheiros .crate com uma localização de descarga, sem um package URL pkg:cargo, pelo que não podiam ser comparadas com advisories. Desde o Yocto 6.0, as receitas construídas com a classe Cargo têm um package URL para a própria receita, como pkg:cargo/librsvg; no código atual, as descargas de crates individuais continuam sem nenhum. Verifique o que a sua versão escreve.
  • Custo. O build com a geração de SBOM do Yocto demorou 155 min 40 s e escreveu 1.632 ficheiros SPDX. Sem ela, o build demorou 88 min 48 s, menos 43%. SPDX_INCLUDE_SOURCES, SPDX_INCLUDE_COMPILED_SOURCES, SPDX_INCLUDE_KERNEL_CONFIG e SPDX_INCLUDE_PACKAGECONFIG estavam ativos, pelo que uma configuração predefinida custa menos. A própria documentação do Yocto avisa que, com as fontes compiladas incluídas, a SBOM não comprimida de core-image-minimal "pode crescer de centenas de megabytes para vários gigabytes".

As receitas nativas, como cmake, llvm, ninja e qemu, estão na SBOM do Yocto. O método, ambas as SBOM e o relatório completo estão em builds Yocto no CRACI.

CVE do kernel Linux: o problema por configuração

O projeto do kernel Linux anunciou a 13 de fevereiro de 2024 que se tinha tornado uma CVE Numbering Authority, e atribui CVE às correções com generosidade. A sua documentação sobre CVE diz que a aplicabilidade de qualquer CVE específica "cabe ao utilizador do Linux determinar", porque "não conhecemos o seu caso de utilização e não sabemos que partes do kernel utiliza".

Assim, uma correspondência pela versão do kernel produz centenas de resultados, a maioria para código que a sua configuração nunca compila. Quatro plataformas de hardware com quatro configurações do kernel dão quatro respostas diferentes a partir da mesma versão do kernel. Há quatro formas de lidar com isto:

  1. Apenas correspondência de versões. Todas as CVE da versão são reportadas. Ruído máximo.
  2. Listas de exclusão curadas. Entradas CVE_STATUS geradas a partir dos dados de CVE do kernel. Em maio de 2026, o oe-core removeu a sua lista gerada para linux-yocto, porque o sbom-cve-check faz isto ele próprio a partir da lista de CVE que o kernel fornece, com um relatório de CVE inalterado e um SPDX quase 20 MB mais pequeno.
  3. Filtragem pelo que foi compilado. Com SPDX_INCLUDE_COMPILED_SOURCES ativo para a receita do kernel, o improve_kernel_cve_report.py verifica se os ficheiros afetados por uma CVE foram usados para construir o kernel. O manual de segurança do Yocto diz que "reduz os falsos positivos de CVE em 70%-80%".
  4. Registo da configuração. SPDX_INCLUDE_KERNEL_CONFIG (6.0) escreve a configuração do kernel na SBOM, para que a resposta possa ser verificada mais tarde.

Exemplo prático. Uma CVE do kernel num driver de rede. A plataforma A compila o driver; a plataforma B não.

Plataforma Driver compilado? Correspondência de versões Filtro de fontes compiladas
A Sim Reportada Reportada: os ficheiros afetados foram compilados
B Não Reportada Não reportada: os ficheiros afetados não foram compilados

Para ter hoje relatórios de CVE do kernel por plataforma, execute as ferramentas de fontes compiladas do Yocto uma vez por configuração de máquina. É a configuração que decide a resposta, pelo que o relatório tem de vir do build de cada configuração.

Caches, mirrors e vendoring: onde qualquer ferramenta de registo tem de ter cuidado

  • Um build que restaura tudo a partir do sstate ou de um DL_DIR preenchido obtém pouco ou nada. Uma ferramenta de registo que vê as obtenções tem de transportar as suas provas com essas caches, ou o registo encolhe.
  • Uma receita que aponta para um tarball com dependências já incluídas mostra uma descarga, não os crates ou módulos que contém.
  • Use o que usar, construa as imagens de release a partir de um estado de cache conhecido, mantenha mirrors que controla e compare o número de componentes entre builds.

No CRACI, os pacotes restaurados a partir de caches de CI permanecem na SBOM, e o estado de completude de cada job assinala o que o registo não conseguiu ver.

O que executar: uma tabela de decisão

Situação O que usar O que obtém O que continua a faltar
Constrói a imagem em GitHub Actions Registe o build (CRACI); mantenha o create-spdx se depende do seu estado de patches e CVE Pacotes do anfitrião, fontes e Actions obtidas, um URL pkg:cargo por crate, monitorização contínua Filtragem do kernel por configuração: use as ferramentas do Yocto
Constrói com Yocto noutro sistema de CI ou num servidor de build create-spdx com sbom-cve-check (ou cve-check em versões mais antigas), filtragem do kernel com fontes compiladas Receitas, patches, estado das CVE como VEX Um inventário dos pacotes do anfitrião e das ferramentas obtidas, mantido à parte
Recebe firmware que não constrói Análise de binários, e uma SBOM do build pedida ao fornecedor Componentes deduzidos a partir do binário Certeza sobre versões, patches e entradas do build
Precisa das CVE do kernel por plataforma Ferramentas de fontes compiladas do Yocto, por configuração de máquina CVE do código que cada configuração constrói Componentes que não são do kernel, a partir da sua SBOM
Só tem um scanner de imagens Use-o para os pacotes instalados, se a base de dados de pacotes for mantida Parte da lista de pacotes em runtime Tudo o que é compilado para dentro, corrigido com patches ou deixado no anfitrião de build; um resultado limpo não é prova

O que cada método vê

Classe de componente Scanner de imagens Análise de binários Yocto create-spdx Registo do build (CRACI)
Pacotes instalados Só se a base de dados de pacotes for mantida Deduzidos a partir de ficheiros Sim Sim, a partir das fontes que o build obteve
Bibliotecas estáticas Não Deduzidas a partir de assinaturas Sim, como receitas Sim, a partir das fontes que o build obteve
Crates Rust Não Deduzidos; as fronteiras entre crates desaparecem Como descargas .crate, sem package URL por crate Sim, cada um com um package URL pkg:cargo
Módulos Go Não Deduzidos a partir do binário Como descargas de módulos da receita Sim, quando obtidos durante o build
Patches aplicados e estado das CVE Não Não Sim, como VEX Não
Configuração do kernel Não Não Sim, com SPDX_INCLUDE_KERNEL_CONFIG (6.0) Não
Ferramentas do anfitrião na máquina de build Não Não Não (receitas nativas, sim) Sim
Ferramentas de build obtidas fora das receitas, e GitHub Actions Não Não Não Sim

Onde entra o CRACI

Para builds Yocto que correm em GitHub Actions, o CRACI é o runner, com até 32 vCPUs e 96 GB de RAM. Regista o que o build trouxe, incluindo pacotes do anfitrião, fontes e Actions do GitHub e outras fontes obtidas, com um package URL para cada crate Rust: na comparação publicada, todos os componentes da SBOM do Yocto e mais 88 que esta não tinha. Compara os componentes com advisories, continua a reavaliar a SBOM à medida que são publicados novos e mostra que builds continham uma dependência vulnerável.

O BitBake já consegue restringir o seu fetcher com BB_ALLOWED_NETWORKS. A política de egress do CRACI acrescenta um segundo controlo no runner, verificado antes do início do job e que falha em modo fechado, para que um script ou uma ferramenta que contorne o fetcher continue sem conseguir chegar a um anfitrião que não autorizou.

Em termos de cobertura da cadeia de abastecimento, a SBOM do CRACI pode substituir o create-spdx. O SPDX do Yocto continua a conter os patches aplicados e as CVE marcadas como corrigidas, que o CRACI não regista, por isso mantenha o create-spdx ativo se depende deles. A documentação do CRACI inclui um exemplo que constrói core-image-sato. Porque é que registar é, em geral, melhor do que analisar explica-se em SBOM no momento do build; as ferramentas para Yocto são comparadas em ferramentas de segurança embebida comparadas e CRACI vs Timesys Vigiles.

Quando o CRACI não é a resposta

  • Depende do estado das CVE ao nível dos patches, como as decisões CVE_STATUS e as CVE corrigidas ou ignoradas como VEX. Isso está no SPDX do Yocto: mantenha-o.
  • Precisa hoje de relatórios de CVE do kernel por configuração. Use as ferramentas de fontes compiladas do Yocto.
  • Não constrói o firmware. Use a análise de binários.
  • Os seus builds Yocto correm fora do GitHub Actions, ou têm de correr na sua própria infraestrutura. O CRACI oferece hoje runners geridos em infraestrutura europeia; outros sistemas de CI e runners alojados pelo cliente estão no roadmap.
  • Precisa da SBOM do job Yocto especificamente em SPDX. A SBOM do CRACI na comparação publicada era CycloneDX; a SBOM do próprio Yocto é SPDX.

Constrói dispositivos ligados para o mercado da UE? Leia o que o CRA exige, como funciona o VEX e como o CRACI se adequa a equipamento de telecomunicações e de rede, IoT industrial e eletrónica de consumo.

Yocto CVE check e SBOM: perguntas frequentes

Porque é que a minha ferramenta de SCA não consegue analisar os nossos produtos baseados em Yocto?

Porque a maioria das ferramentas de SCA lê manifestos, lockfiles ou a base de dados de pacotes de uma imagem, e um build Yocto decide o seu conteúdo dentro do BitBake. As imagens de produção deixam muitas vezes de fora a base de dados de pacotes, as bibliotecas estáticas e os crates Rust são compilados para dentro dos binários, os patches das receitas mantêm os números de versão upstream e as ferramentas do anfitrião de build nunca chegam à imagem.

Posso analisar uma imagem Yocto ou um firmware com o Trivy, o Grype ou um scanner de binários?

Pode, e obterá uma resposta parcial. Um scanner de imagens lê os pacotes instalados se a base de dados de pacotes for mantida, e não vê o que está compilado lá dentro. Um scanner de binários deduz componentes a partir de strings e assinaturas e tem de adivinhar perante binários stripped, código estático e Rust compilado. Nenhum dos dois vê o anfitrião de build nem os patches que uma receita aplicou.

A SBOM do Yocto inclui crates Rust e módulos Go?

Lista-os como fontes da receita que os utiliza. Na versão que construímos, cada crate Rust aparecia como uma descarga .crate com uma localização de descarga e sem package URL pkg:cargo. Desde o Yocto 6.0, as receitas construídas com as classes Cargo e Go recebem um package URL do ecossistema para a própria receita, não para cada descarga de crate ou de módulo.

Porque é que o meu scanner reporta CVE que as nossas receitas Yocto já corrigem?

Porque compara números de versão. Uma receita Yocto mantém a versão upstream e aplica as correções de segurança como patches, marcados com uma linha CVE: ou registados em CVE_STATUS. Uma correspondência por intervalo de versões não consegue ver o patch. O próprio SPDX do Yocto regista essas CVE como corrigidas, ligadas aos ficheiros de patch.

O que substituiu o cve-check no Yocto?

A classe sbom-cve-check, no Yocto 6.0. Executa o sbom-cve-check da Bootlin sobre o resultado SPDX do build. As versões 5.0 a 5.3 continuam a ter o cve-check, que comparava nomes e versões de receitas; as notas de lançamento da 5.2 avisam que os seus relatórios podem deixar escapar vulnerabilidades porque muitas CVE já não trazem dados CPE.

Como obtenho as CVE do kernel Linux para a minha própria configuração do kernel?

Ative SPDX_INCLUDE_COMPILED_SOURCES para a receita do kernel e execute o improve_kernel_cve_report.py, que verifica se os ficheiros afetados por cada CVE foram compilados. O manual de segurança do Yocto diz que reduz os falsos positivos de CVE em 70% a 80%. Execute-o por configuração de máquina, uma vez que cada configuração constrói código diferente.

A cache shared state afeta a SBOM?

Pode afetar. As tarefas restauradas a partir do sstate saltam a obtenção e a compilação, pelo que uma ferramenta que dependa de observar esses passos vê menos. O create-spdx do Yocto trabalha a partir dos metadados das receitas. Seja qual for o método, construa as imagens de release a partir de um estado de cache conhecido e compare o número de componentes entre builds.

A SBOM integrada do Yocto é suficiente para o CRA?

O CRA exige uma SBOM que abranja pelo menos as dependências de nível superior, e a SBOM do Yocto é exaustiva em relação ao que o BitBake constrói. Não lista os pacotes do anfitrião na máquina de build, as GitHub Actions nem as ferramentas obtidas fora das receitas. Se isso é suficiente, cabe-lhe a si decidir; a SBOM é uma prova do seu processo, não conformidade por si só.

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 foi obtido.

Marcar demo