Yocto
Por qué los escáneres SBOM no ven lo que contienen los builds de Yocto
Los escáneres leen un resultado, como un sistema de archivos, un binario o un manifiesto, y deducen lo que entró. Una imagen de Yocto oculta la mayor parte: las bibliotecas estáticas y los crates de Rust se compilan dentro de los binarios, los parches de las recetas cambian el código sin cambiar los números de versión, la configuración del kernel decide qué código existe siquiera, y las herramientas del host de build nunca llegan a la imagen. La alternativa es registrar el build y conservar los metadatos de parches y CVE del propio Yocto.
Actualizado el
En un minuto
- Host de build: las herramientas de la máquina de build dan forma a la imagen y nunca aparecen en ella. Un escáner de la imagen no puede verlas.
- Descarga: BitBake descarga fuentes, crates de Rust, módulos de Go y herramientas. Un escáner solo ve lo que sobrevive en la imagen.
- Recetas y parches: una receta mantiene la versión upstream y aplica encima parches de seguridad. Un escáner que coteja versiones informa de CVE que ya están corregidos.
- Código compilado: las bibliotecas estáticas, los crates y la configuración del kernel acaban dentro de los binarios. Un escáner ve un solo archivo donde entraron decenas de componentes.
- Imagen: las imágenes de producción suelen prescindir de la base de datos de paquetes. Entonces el escáner no tiene ninguna lista que leer e informa de poco o nada.
En qué se diferencia un build de Yocto de lo que esperan los escáneres
Un build de Yocto no es una instalación con un gestor de paquetes. La mayor parte de lo que acaba en el dispositivo se decide en tiempo de build, dentro de BitBake, en cinco capas. Los escáneres miran una capa a posteriori y tienen que adivinar el resto.
1. El host de build
BitBake se ejecuta con herramientas de la máquina de build. La variable HOSTTOOLS enumera las herramientas del host de build
a las que pueden llamar las tareas de build, y el sistema de build crea enlaces simbólicos a ellas en ${TMPDIR}/hosttools. BitBake también
compila sus propias herramientas mediante recetas -native y -cross. Las herramientas del host influyen en la imagen y,
por diseño, no forman parte de ella.
2. Descarga
Las recetas indican sus fuentes en SRC_URI, y el fetcher las descarga en DL_DIR. Busca
primero en DL_DIR, luego en PREMIRRORS, después upstream y por último en MIRRORS. Los crates de Rust
llegan mediante el fetcher crate://, enumerados en un archivo -crates.inc que
cargo-update-recipe-crates genera a partir de Cargo.lock. Los módulos de Go llegan mediante la
clase go-mod o se incluyen con vendoring mediante go-vendor. BB_NO_NETWORK y
BB_ALLOWED_NETWORKS controlan a qué puede acceder el fetcher.
3. Recetas y parches
Cada receta fija una versión upstream en PV y aplica parches encima. Un parche con una línea CVE:
en su cabecera marca ese CVE como parcheado. El número de versión sigue siendo el upstream, así que la receta puede estar corregida
aunque su versión diga lo contrario.
4. Código compilado
Las bibliotecas estáticas (los paquetes -staticdev), los crates de Rust y los módulos de Go acaban dentro de los binarios que
los usan. El kernel y sus módulos se compilan a partir de una configuración específica del producto, así que dos plataformas con la misma versión
del kernel contienen código distinto.
5. La imagen
El sistema de archivos raíz. La característica de imagen package-management instala herramientas de gestión de paquetes y
conserva la base de datos del gestor de paquetes. Sin ella, los archivos de datos del gestor de paquetes se eliminan del sistema de archivos
raíz, algo habitual en las imágenes de producción.
La caché shared state (sstate), o de estado compartido
BitBake puede restaurar el resultado de una tarea desde la caché shared state en lugar de ejecutarla. El manual de introducción de Yocto lo dice sin rodeos: si los objetos precompilados están disponibles, el compilador no hace falta, "por tanto, el compilador ni siquiera se descarga". Las tareas restauradas desde sstate se saltan la descarga, la compilación y la instalación, lo que importa a cualquier herramienta que dependa de observar esos pasos. Más sobre ello en la sección sobre cachés, más abajo.
Por qué los escáneres de imágenes y de sistemas de archivos no ven la mayor parte
-
Sin base de datos de paquetes. Una imagen de producción compilada sin
package-managementno le da al escáner ninguna lista que leer, así que recurre a heurísticas de archivos o no informa de casi nada. El resultado parece completo y está casi vacío. -
Código estático e incluido con vendoring. Una biblioteca estática o un crate compilado dentro de
/usr/bin/foono deja ningún registro de paquete.librsvges un ejemplo: la receta actual de oe-core enumera más de 350 crates de Rust, y en el dispositivo es una sola biblioteca compartida. -
Host de build y herramientas descargadas. Nunca están en la imagen y, por tanto, nunca en un escaneo de la imagen, aunque una
herramienta del host o una GitHub Action comprometida pueda comprometer la imagen. La puerta trasera de xz utils (CVE-2024-3094) entró en la
biblioteca mientras se compilaba, desde los tarballs de la release y no desde el repositorio Git. En marzo de 2025, CISA informó
de que todas las versiones de la GitHub Action
tj-actions/changed-filesestuvieron comprometidas durante tres días. -
Parches aplicados. La imagen dice
opensslen una versión upstream. La receta aplicó la corrección de un CVE que afecta a esa versión y etiquetó el parche conCVE:. Un cotejo por rango de versiones lo marca de todos modos. Es la forma que adopta en Yocto el problema de los backports de las distribuciones, y una de las principales fuentes del ruido que se trata en cómo reducir el ruido de vulnerabilidades.
El resultado es una mezcla de componentes que faltan y hallazgos erróneos, y nada en él le dice cuál es cuál. El mismo argumento se aplica a los contenedores en SBOM de imágenes Docker y a los proyectos de lenguajes en generadores de SBOM de código abierto.
Por qué el escaneo binario de firmware tiene que adivinar
El análisis binario coteja cadenas, símbolos y firmas de código del firmware extraído con componentes conocidos y después deduce las versiones. Cuando el binario contiene pruebas claras, funciona. En una imagen de Yocto, a menudo tiene que adivinar:
- binarios con símbolos eliminados y sin cadenas de versión;
- código enlazado estáticamente, donde los límites entre bibliotecas han desaparecido;
- Rust compilado, donde los límites entre crates desaparecen en un único ejecutable;
- parches con backport, que son invisibles en un número de versión;
- código del kernel que la configuración incluyó o excluyó al compilar.
El análisis binario es la herramienta adecuada para el firmware que usted no ha compilado: blobs de proveedores, módulos comprados, un dispositivo que está evaluando. Si no tiene el build, analizar el binario es la única opción. La regla de decisión es sencilla: si lo compila, regístrelo; si solo lo recibe, analícelo y pida al proveedor una SBOM de su build.
Lo que hacen bien las herramientas de SBOM y CVE del propio Yocto
El trabajo del Yocto Project en SBOM es buena ingeniería, y sabe cosas que ninguna herramienta externa puede saber. Su documentación dice que la SBOM es "una descripción de todos los componentes que ha utilizado, sus licencias, sus dependencias, sus fuentes, los cambios que se les aplicaron y las vulnerabilidades conocidas que se corrigieron".
create-spdx por versión
- 4.3 (Nanbield): la generación de SPDX está activada por defecto.
- 5.1 (Styhead): SPDX 3.0 por defecto en lugar de 2.2, y una clase
vexque proporciona a las herramientas de CVE externas la información que necesitan. - 5.3 (Whinlatter):
SPDX_INCLUDE_COMPILED_SOURCES, que incluye solo las fuentes usadas para compilar. - 6.0 (Wrynose, soporte a largo plazo): se elimina SPDX 2.2; se añaden
SPDX_INCLUDE_KERNEL_CONFIGySPDX_INCLUDE_PACKAGECONFIG; las recetas compiladas con las clases Cargo, Go, PyPI, npm y CPAN reciben un package URL de su ecosistema.
La SBOM cubre lo que compila BitBake, incluidas las herramientas nativas que compila para el host. Es exhaustiva con todo lo que tiene una receta.
El estado de los CVE como VEX dentro de la SBOM
En SPDX 3, el sistema de build escribe el estado de los CVE de cada receta como relaciones VEX: un CVE parcheado pasa a ser "fixed",
vinculado a los archivos de parche; uno sin parchear, "affected"; uno ignorado, "not affected", con el motivo como impact
statement. SPDX_INCLUDE_VEX fija cuánto se incluye: none, current (el valor por defecto,
vulnerabilidades que no están ya corregidas en la fuente upstream) o all.
CVE_STATUS y la etiqueta del parche
CVE_STATUS registra una decisión por CVE, como un motivo y una descripción opcional. Los motivos corresponden a
parcheado (backported-patch, cpe-stable-backport, fixed-version y otros),
sin parchear (vulnerable-investigating) e ignorado (cpe-incorrect, disputed,
not-applicable-config, not-applicable-platform, upstream-wontfix).
CVE_STATUS_GROUPS aplica una decisión a un grupo de CVE, y CVE_PRODUCT fija el nombre de producto
que se usa para el cotejo.
# 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
cve-check cotejaba los nombres de las recetas (CVE_PRODUCT) y sus versiones con datos de vulnerabilidades. Las
notas de la versión 5.2 advierten de que, desde principios de 2024, los responsables de la NVD dejaron de anotar muchos CVE con los
CPE afectados, de modo que "los informes de CVE actuales pueden parecer buenos, pero la realidad es que algunas vulnerabilidades simplemente no
se notifican". La 5.2 también convirtió el feed de FKIE en el predeterminado en lugar de la NVD. Yocto 6.0 eliminó cve-check y
lo sustituyó por la clase sbom-cve-check, que ejecuta
sbom-cve-check de Bootlin sobre
la salida SPDX. En las versiones 5.0 a 5.3 sigue teniendo cve-check; trátelo como heredado.
Dónde se detiene la SBOM de Yocto
Lo que Yocto no puede ver es todo lo que queda fuera de los metadatos de BitBake. Compilamos core-image-sato dos veces en un
runner ARM64 nativo con 32 vCPU, una vez con la generación de SBOM de Yocto y otra sin ella, y comparamos la SBOM SPDX
3.0.1 de Yocto, escrita como 1.632 archivos, con la SBOM CycloneDX que registró CRACI:
-
Componentes. La SBOM registrada por CRACI tenía todos los componentes de la SBOM de Yocto y 88 más que esta no recogía: 23 paquetes
del host en la máquina de build (como
cpiode Ubuntu), 10 fuentes de GitHub, entre ellas la GitHub Actionactions/upload-artifact, y 55 fuentes y herramientas más descargadas durante el build. -
Crates de Rust. Ambas enumeraban las mismas 653 versiones de crates de Rust. En la versión que compilamos, la SBOM de Yocto
las enumeraba solo como archivos
.cratecon una ubicación de descarga, sin un package URLpkg:cargo, así que no se podían cotejar con advisories. Desde Yocto 6.0, las recetas compiladas con la clase Cargo llevan un package URL para la propia receta, comopkg:cargo/librsvg; en el código actual, las descargas de crates individuales siguen sin tenerlo. Compruebe qué escribe su versión. -
Coste. El build con la generación de SBOM de Yocto tardó 155 min 40 s y escribió 1.632 archivos SPDX. Sin
ella, el build tardó 88 min 48 s, un 43 % menos.
SPDX_INCLUDE_SOURCES,SPDX_INCLUDE_COMPILED_SOURCES,SPDX_INCLUDE_KERNEL_CONFIGySPDX_INCLUDE_PACKAGECONFIGestaban activados, así que una configuración por defecto cuesta menos. La propia documentación de Yocto advierte de que, con las fuentes compiladas incluidas, la SBOM sin comprimir decore-image-minimal"puede pasar de cientos de megabytes a varios gigabytes".
Las recetas nativas como cmake, llvm, ninja y qemu están en la
SBOM de Yocto. El método, ambas SBOM y el informe completo están en builds de Yocto en CRACI.
CVE del kernel Linux: el problema de cada configuración
El proyecto del kernel Linux anunció el 13 de febrero de 2024 que se había convertido en CVE Numbering Authority, y asigna CVE a las correcciones con generosidad. Su documentación sobre CVE dice que la aplicabilidad de un CVE concreto "corresponde determinarla al usuario de Linux", porque "no conocemos su caso de uso y no sabemos qué partes del kernel utiliza".
Así que un cotejo por versión del kernel produce cientos de hallazgos, la mayoría de código que su configuración nunca compila. Cuatro plataformas de hardware con cuatro configuraciones del kernel dan cuatro respuestas distintas a partir de la misma versión del kernel. Hay cuatro formas de abordarlo:
- Solo cotejo de versiones. Se informa de todos los CVE de la versión. Máximo ruido.
-
Listas de exclusión curadas. Entradas
CVE_STATUSgeneradas a partir de los datos de CVE del kernel. En mayo de 2026, oe-core eliminó su lista generada paralinux-yocto, porquesbom-cve-checklo hace por sí mismo a partir de la lista de CVE que publica el kernel, con un informe de CVE sin cambios y un SPDX casi 20 MB más pequeño. -
Filtrar por lo que se compiló. Con
SPDX_INCLUDE_COMPILED_SOURCESactivado para la receta del kernel,improve_kernel_cve_report.pycomprueba si los archivos a los que afecta un CVE se usaron para compilar el kernel. El manual de seguridad de Yocto dice que "reduce los falsos positivos de CVE en un 70 %-80 %". - Registrar la configuración.
SPDX_INCLUDE_KERNEL_CONFIG(6.0) escribe la configuración del kernel en la SBOM, para que la respuesta pueda comprobarse más adelante.
Ejemplo práctico. Un CVE del kernel en un driver de red. La plataforma A compila el driver; la plataforma B, no.
| Plataforma | ¿Driver compilado? | Cotejo por versión | Filtro de fuentes compiladas |
|---|---|---|---|
| A | Sí | Notificado | Notificado: los archivos afectados se compilaron |
| B | No | Notificado | No notificado: los archivos afectados no se compilaron |
Para obtener hoy informes de CVE del kernel por plataforma, ejecute las herramientas de fuentes compiladas de Yocto una vez por cada configuración de máquina. La configuración es lo que decide la respuesta, así que el informe tiene que salir del build de cada configuración.
Cachés, mirrors y vendoring: donde cualquier registro debe tener cuidado
-
Un build que lo restaura todo desde sstate o desde un
DL_DIRya poblado descarga poco o nada. Una herramienta que registra las descargas tiene que llevar sus pruebas junto con esas cachés, o el registro se reduce. - Una receta que apunta a un tarball con vendoring previo muestra una descarga, no los crates ni los módulos que contiene.
- Use lo que use, compile las imágenes de release desde un estado de caché conocido, mantenga mirrors bajo su control y compare el número de componentes entre builds.
En CRACI, los paquetes restaurados desde cachés de CI siguen en la SBOM, y el estado de completitud de cada job señala lo que el registro no pudo ver.
Qué ejecutar: una tabla de decisión
| Situación | Qué usar | Qué obtiene | Qué le sigue faltando |
|---|---|---|---|
| Compila la imagen en GitHub Actions | Registre el build (CRACI); mantenga create-spdx si depende de su estado de parches y CVE |
Paquetes del host, fuentes y Actions descargadas, un URL pkg:cargo por crate, monitorización continua |
Filtrado del kernel por configuración: use las herramientas de Yocto |
| Compila con Yocto en otro sistema de CI o en un servidor de build | create-spdx con sbom-cve-check (o cve-check en versiones anteriores), filtrado del kernel con fuentes compiladas |
Recetas, parches, estado de los CVE como VEX | Un inventario de paquetes del host y herramientas descargadas, llevado por separado |
| Recibe firmware que no compila usted | Análisis binario y una SBOM del build por parte del proveedor | Componentes deducidos del binario | Certeza sobre versiones, parches y entradas del build |
| Necesita los CVE del kernel por plataforma | Las herramientas de fuentes compiladas de Yocto, por configuración de máquina | CVE del código que compila cada configuración | Los componentes ajenos al kernel, a partir de su SBOM |
| Solo dispone de un escáner de imágenes | Úselo para los paquetes instalados, si se conserva la base de datos de paquetes | Parte de la lista de paquetes en tiempo de ejecución | Todo lo compilado dentro, parcheado o que se queda en el host de build; un resultado limpio no es una prueba |
Qué ve cada método
| Clase de componente | Escáner de imágenes | Análisis binario | Yocto create-spdx |
Registro del build (CRACI) |
|---|---|---|---|---|
| Paquetes instalados | Solo si se conserva la base de datos de paquetes | Deducidos de los archivos | Sí | Sí, a partir de las fuentes que descargó el build |
| Bibliotecas estáticas | No | Deducidas de firmas | Sí, como recetas | Sí, a partir de las fuentes que descargó el build |
| Crates de Rust | No | Deducidos; los límites entre crates desaparecen | Como descargas .crate, sin package URL por crate |
Sí, cada uno con un package URL pkg:cargo |
| Módulos de Go | No | Deducidos del binario | Como descargas de módulos de la receta | Sí, cuando se descargan durante el build |
| Parches aplicados y estado de los CVE | No | No | Sí, como VEX | No |
| Configuración del kernel | No | No | Sí, con SPDX_INCLUDE_KERNEL_CONFIG (6.0) |
No |
| Herramientas del host en la máquina de build | No | No | No (recetas nativas, sí) | Sí |
| Herramientas de build descargadas fuera de las recetas, y GitHub Actions | No | No | No | Sí |
Dónde encaja CRACI
Para los builds de Yocto que se ejecutan en GitHub Actions, CRACI es el runner, con hasta 32 vCPU y 96 GB de RAM. Registra lo que incorporó el build, incluidos los paquetes del host, las fuentes y Actions de GitHub y otras fuentes descargadas, con un package URL para cada crate de Rust: en la comparación publicada, todos los componentes de la SBOM de Yocto y 88 más que esta no recogía. Coteja los componentes con advisories, sigue reevaluando la SBOM a medida que se publican otros nuevos y muestra qué builds contenían una dependencia vulnerable.
BitBake ya puede restringir su fetcher con BB_ALLOWED_NETWORKS. La
política de salida de CRACI añade un segundo control en el runner, comprobado antes de que empiece
el job y que bloquea en caso de fallo, de modo que un script o una herramienta que esquive el fetcher sigue sin poder acceder a un host que usted no
haya permitido.
En cuanto a la cobertura de la cadena de suministro, la SBOM de CRACI puede sustituir a create-spdx. El SPDX de Yocto sigue incluyendo los
parches aplicados y los CVE marcados como corregidos, que CRACI no registra, así que mantenga create-spdx activado si depende de
ellos. La documentación de CRACI incluye un ejemplo que compila core-image-sato. Por qué registrar supera a escanear en
general se explica en SBOM en tiempo de build; las herramientas para Yocto se comparan en
comparativa de herramientas de seguridad para sistemas embebidos y
CRACI frente a Timesys Vigiles.
Cuándo CRACI no es la respuesta
- Depende del estado de los CVE a nivel de parche, como las decisiones de
CVE_STATUSy los CVE parcheados o ignorados como VEX. Eso está en el SPDX de Yocto: consérvelo. - Necesita hoy informes de CVE del kernel por configuración. Use las herramientas de fuentes compiladas de Yocto.
- No compila usted el firmware. Use el análisis binario.
- Sus builds de Yocto se ejecutan fuera de GitHub Actions o deben ejecutarse en su propia infraestructura. CRACI ofrece hoy runners gestionados en infraestructura europea; otros sistemas de CI y los runners alojados por el cliente están en la hoja de ruta.
- Necesita específicamente la SBOM del job de Yocto en SPDX. La SBOM de CRACI en la comparación publicada era CycloneDX; la SBOM propia de Yocto es SPDX.
¿Fabrica dispositivos conectados para el mercado de la UE? Lea qué exige el CRA, cómo funciona VEX y cómo encaja CRACI en telecomunicaciones y equipos de red, IoT industrial y electrónica de consumo.
Yocto CVE check y SBOM: preguntas frecuentes
¿Por qué mi herramienta SCA no puede escanear nuestros productos basados en Yocto?
Porque la mayoría de las herramientas SCA leen manifiestos, lockfiles o la base de datos de paquetes de una imagen, y un build de Yocto decide su contenido dentro de BitBake. Las imágenes de producción suelen prescindir de la base de datos de paquetes, las bibliotecas estáticas y los crates de Rust se compilan dentro de los binarios, los parches de las recetas dejan intactos los números de versión upstream y las herramientas del host de build nunca llegan a la imagen.
¿Puedo escanear una imagen de Yocto o un firmware con Trivy, Grype o un escáner binario?
Puede, y obtendrá una respuesta parcial. Un escáner de imágenes lee los paquetes instalados si se conserva la base de datos de paquetes, y no ve lo que está compilado dentro. Un escáner binario deduce los componentes a partir de cadenas y firmas, y tiene que adivinar con binarios sin símbolos, código estático y Rust compilado. Ninguno ve el host de build ni los parches que aplicó una receta.
¿Incluye la SBOM de Yocto los crates de Rust y los módulos de Go?
Los enumera como fuentes de la receta que los usa. En la versión que compilamos, cada crate de Rust aparecía como una descarga .crate con una ubicación de descarga y sin package URL pkg:cargo. Desde Yocto 6.0, las recetas compiladas con las clases Cargo y Go reciben un package URL de su ecosistema para la propia receta, no para cada descarga de crate o módulo.
¿Por qué mi escáner informa de CVE que nuestras recetas de Yocto ya parchean?
Porque coteja números de versión. Una receta de Yocto mantiene la versión upstream y aplica las correcciones de seguridad como parches, etiquetados con una línea CVE: o registrados en CVE_STATUS. Un cotejo por rango de versiones no puede ver el parche. El propio SPDX de Yocto registra esos CVE como corregidos, vinculados a los archivos de parche.
¿Qué sustituyó a cve-check en Yocto?
La clase sbom-cve-check, en Yocto 6.0. Ejecuta sbom-cve-check de Bootlin sobre la salida SPDX del build. Las versiones 5.0 a 5.3 siguen teniendo cve-check, que cotejaba nombres y versiones de recetas; las notas de la versión 5.2 advierten de que sus informes pueden pasar por alto vulnerabilidades porque muchos CVE ya no incluyen datos de CPE.
¿Cómo obtengo los CVE del kernel Linux para mi propia configuración del kernel?
Active SPDX_INCLUDE_COMPILED_SOURCES para la receta del kernel y ejecute improve_kernel_cve_report.py, que comprueba si se compilaron los archivos a los que afecta cada CVE. El manual de seguridad de Yocto dice que reduce los falsos positivos de CVE entre un 70 % y un 80 %. Ejecútelo por cada configuración de máquina, ya que cada configuración compila un código distinto.
¿Afecta la caché shared state a la SBOM?
Puede afectarle. Las tareas restauradas desde sstate se saltan la descarga y la compilación, así que una herramienta que dependa de observar esos pasos ve menos. El create-spdx de Yocto trabaja a partir de los metadatos de las recetas. Con cualquier método, compile las imágenes de release desde un estado de caché conocido y compare el número de componentes entre builds.
¿Basta la SBOM integrada de Yocto para el CRA?
El CRA pide una SBOM que cubra al menos las dependencias de primer nivel, y la SBOM de Yocto es exhaustiva con lo que compila BitBake. No enumera los paquetes del host en la máquina de build, las GitHub Actions ni las herramientas descargadas fuera de las recetas. Si eso basta es decisión suya; la SBOM es una prueba de su proceso, no el cumplimiento en sí.
Traiga un build de Yocto a la demo
Reserve una demo y ejecutaremos uno de sus builds de BitBake en un runner de CRACI y revisaremos con usted lo que descargó.
Reservar una demo