Yocto
SBOM y builds de Yocto en CRACI
Yocto puede escribir una SBOM detallada en SPDX para cada imagen. En un build comparativo, la SBOM registrada por CRACI tenía todos los componentes de la de Yocto, 88 que a esta se le escaparon y un package URL para cada uno de los 653 crates de Rust que Yocto enumera sin él, con un 43% menos de tiempo de build.
Actualizado el
Build comparativo: core-image-sato
Cómo generar una SBOM con Yocto
El sistema de build OpenEmbedded escribe SBOM en SPDX mediante la clase create-spdx. Que esté activada, y qué versión de SPDX escribe, depende de la versión de Yocto:
- Kirkstone (4.0): desactivada por defecto. Añada
INHERIT += "create-spdx". SPDX 2.2. - Nanbield (4.3): a partir de esta versión, la generación de SBOM está activada por defecto.
- Scarthgap (5.0): activada por defecto, SPDX 2.2. SPDX 3.0 está disponible mediante la clase
create-spdx-3.0. - Styhead (5.1) y posteriores: activada por defecto, SPDX 3.0.
Se configura en un archivo de configuración como conf/local.conf. En una versión actual no suele hacer falta añadir nada; para desactivarla, 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" Otras variables SPDX_ añaden detalle. SPDX_INCLUDE_SOURCES describe los archivos fuente de cada herramienta del host y de cada paquete de destino, lo que aumenta mucho el tamaño de la salida. Las versiones recientes añaden opciones para la configuración del kernel, las funciones de PACKAGECONFIG, la información del proveedor y los package URLs de las fuentes Cargo, Go, PyPI, npm y CPAN.
Dónde se guardan los archivos de la SBOM
Al compilar una imagen, la SBOM de nivel superior aparece junto a ella, como IMAGE-MACHINE.spdx.json en tmp/deploy/images/MACHINE/ dentro del directorio de build. Los archivos relacionados están en el mismo directorio y en tmp/deploy/spdx. En Kirkstone, los documentos por receta vienen en un archivo 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 con meta-cyclonedx
Yocto por sí solo escribe únicamente SPDX. Para CycloneDX, la capa meta-cyclonedx genera una SBOM a partir del sistema de archivos raíz de la imagen, además de un archivo VEX independiente con las CVE parcheadas e ignoradas que conoce el sistema de build. Descargue la rama de la capa correspondiente a su versión, añádala a sus capas y herede su clase:
# 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" Los archivos se guardan junto a la imagen en DEPLOY_DIR_IMAGE, con los sufijos .cyclonedx.bom.json y .cyclonedx.vex.json. La versión por defecto es CycloneDX 1.6, que se define con CYCLONEDX_SPEC_VERSION. Por defecto solo se incluyen los paquetes de tiempo de ejecución, lo que mantiene la SBOM pequeña pero puede dejar fuera componentes que llegan a la imagen sin instalarse como paquetes.
Lo que deja fuera la SBOM de Yocto
La SBOM de Yocto es minuciosa con lo que compila BitBake. En SPDX 3 abarca la imagen, cada receta (incluidas las nativas de tiempo de build), sus fuentes, los parches aplicados y las vulnerabilidades marcadas como corregidas. Para core-image-sato eso supuso 1,632 archivos independientes. Para ver lo que deja fuera, compilamos la imagen en un runner de CRACI, ARM64 nativo con 32 vCPU, y comparamos la SBOM de Yocto con la que registró CRACI, componente a componente, tras normalizar los nombres en todos esos archivos.
De los 953 componentes de la SBOM de CRACI, 865 estaban también en la de Yocto. Ninguno estaba solo en la de Yocto. Las diferencias están en lo que Yocto no puede ver y en cómo identifica lo que sí enumera.
Crates de Rust sin package URL
Ambas SBOM contienen las mismas 653 versiones de 559 crates de Rust, como cairo-rs y zune-jpeg, que librsvg incorpora al compilar. Yocto enumera cada una solo como un archivo .crate y una URL de descarga de crates.io, dentro de la receta que la usa. Ninguna lleva un package URL pkg:cargo. CRACI registra cada crate con uno.
Eso decide si puede monitorizarlos en busca de vulnerabilidades. El cotejo de vulnerabilidades funciona con package URLs: un aviso sobre un crate lo identifica como pkg:cargo/..., y un nombre de archivo dentro de la lista de fuentes de otra receta no da a las herramientas de SBOM y de vulnerabilidades nada con lo que cotejarlo. Con la SBOM de Yocto como única fuente, un crate vulnerable en su imagen pasa sin notificarse.
Con la de CRACI, cada crate se coteja con los avisos, cada paquete del build muestra su estado de vulnerabilidad, y CRACI sigue reevaluando la SBOM a medida que se publican nuevos avisos, mucho después de que terminara el build.
Lo que solo encontró CRACI
Los 88 componentes que faltan en la SBOM de Yocto procedían de fuera de los metadatos de BitBake:
- 23 paquetes del host instalados en la máquina de build, como
cpio2.15,libc6,localesypython3-jinja2de Ubuntu. BitBake se ejecuta con ellos, y la SBOM de Yocto no los enumera. - 10 fuentes de GitHub, entre ellas
patchelf,btrfs-progsy la GitHub Actionactions/upload-artifact, fijadas al commit con el que se ejecutó el workflow - Otras fuentes y herramientas descargadas durante el build, como
pseudo-prebuilt,tzdatay herramientas de build de Python comohatchlingysetuptools_scm
Ninguno de ellos se instala en la imagen, pero todos están en la ruta crítica del build: una herramienta del host o una Action comprometida puede comprometer su imagen sin llegar a formar parte de ella. CRACI los enumera porque ve el tráfico que entra en el build.
Lo que cuesta la SBOM integrada
La generación de SBOM de Yocto no es gratuita. En el mismo runner de 32 vCPU, el build con ella tardó 155 min 40 s y escribió la SBOM en 1,632 archivos SPDX independientes. El build sin ella, con CRACI registrando, tardó 88 min 48 s. A la tarifa de CRACI de $0.002 por vCPU-minuto, eso supone unos $9.96 frente a $5.68 por build, sin contar el tiempo que su equipo pasa esperando.
La diferencia es mayor frente a los runners alojados en GitHub. CRACI ejecuta los builds aproximadamente el doble de rápido gracias a un hardware más rápido, menos tiempo en cola y la caché, así que el mismo build con la SBOM de Yocto en un runner ARM64 de 32 núcleos alojado en GitHub tardaría unos 5 h 11 min. A $0.050 por minuto, eso son $15.60. El build en CRACI cuesta $5.68: un 64% menos, o unas 2,7 veces más barato. Precios de lista de GitHub a septiembre de 2026; los minutos incluidos no cubren los runners más grandes.
La salida SPDX de Yocto sí incluye datos que CRACI no registra, como los parches que aplica una receta y las CVE que marca como corregidas. Si su proceso depende de ellos, mantenga create-spdx activado y utilice la SBOM de CRACI junto a esa salida. Si no, la SBOM de CRACI cubre por sí sola todos los componentes que cubría la de Yocto, y más.
Por qué importa para la seguridad de la cadena de suministro
Lo que entra en un build decide lo que sale de él, se instale o no en la imagen. Los atacantes lo saben, y el build es el punto por el que han entrado los ataques recientes a la cadena de suministro:
- Los ataques se esconden en el build. La puerta trasera de xz utils (CVE-2024-3094) estaba en las versiones 5.6.0 y 5.6.1. Su activador estaba en los tarballs de la versión y no en el repositorio Git, y el código malicioso entró en la biblioteca mientras se compilaba. Leer el código fuente no lo revelaba; saber exactamente qué tarball descargó el build, sí.
- Las dependencias de la CI también son objetivos. En marzo de 2025, la CISA informó de que todas las versiones de la GitHub Action
tj-actions/changed-filesestuvieron comprometidas durante tres días. Una Action se ejecuta dentro de su job de build, y por eso CRACI enumera las que usó su workflow, fijadas al commit que se ejecutó. - Los crates de Rust desaparecen dentro de los binarios. Cargo compila los crates dentro de los programas que los usan, así que un crate vulnerable se distribuye dentro de la imagen sin aparecer nunca como paquete. Si la SBOM lo enumera solo como nombre de archivo, las herramientas de vulnerabilidades tampoco pueden cotejarlo. Escanear después el binario terminado obliga a adivinar lo que entró; registrar el build, no.
- No se puede responder a lo que no se ve. Cuando llega un aviso sobre un crate o una herramienta de build, necesita saber qué builds la usaron. CRACI conserva la SBOM de cada build y muestra qué builds contenían la dependencia vulnerable, directa o transitiva, para que sepa durante qué periodo estuvo afectado. Eso solo funciona si cada componente tiene un package URL con el que cotejarlo.
- Un build solo debería llegar a lo que necesita. La política de salida de CRACI bloquea las conexiones a hosts que el build no necesita, de modo que una dependencia comprometida que intente enviar sus secretos al servidor de un atacante queda bloqueada, incluso en un ataque que nadie ha visto antes.
Los clientes y normativas como el Cyber Resilience Act también exigen a los fabricantes de dispositivos conectados que sepan qué contienen sus productos. Una SBOM que abarca todo el build es una evidencia que se sostiene cuando la piden.
Obtenga la comparativa completa
Las listas de componentes detrás de estas cifras, ambas SBOM y cómo las generamos y comparamos.
- Los 88 componentes que solo encontró CRACI y los 865 que enumeraban ambas SBOM
- Cómo identifica cada SBOM las 653 versiones de crates de Rust
- Ambos archivos de SBOM: el CycloneDX de CRACI y el SPDX de Yocto
- La configuración del build, el tamaño del runner y los tiempos
Gracias, aquí tiene el informe completo
Por qué cuesta ejecutar builds de Yocto en CI
El build de una imagen completa compila desde el código fuente una toolchain, un kernel y cientos de paquetes. En los runners estándar de 2 núcleos que ofrecen la mayoría de los servicios de CI, eso puede llevar horas, así que muchos equipos de sistemas embebidos mantienen un servidor de build dedicado debajo de una mesa o en un rack, y ese servidor se convierte en una máquina más que parchear, de la que hacer copias de seguridad y que justificar ante un auditor.
Un build de Yocto también descarga muchísimo: tarballs de código fuente, repositorios Git y parches de proyectos upstream y mirrors. Esas descargas son lo que su SBOM tiene que reflejar, y lo que normativas como el Cyber Resilience Act exigen que los fabricantes de dispositivos conectados conozcan y controlen.
Lo que CRACI aporta a un build de Yocto
Runners dimensionados para BitBake
Los runners de CRACI escalan de 1 a 32 unidades de cómputo, y cada unidad equivale a 1 vCPU y 3 GB de RAM. Un build de Yocto puede pedir el tamaño más grande, 32 vCPU y 96 GB de RAM, desde el propio workflow. Los jobs se ejecutan en máquinas virtuales aisladas y las ejecuciones siguen apareciendo en GitHub como cualquier otro job de Actions.
Los minutos se miden por segundo y se facturan por vCPU-minuto, así que un runner grande cuesta más por minuto y termina antes. Consulte los precios para ver las tarifas actuales.
Acceso a la red que decide usted
BitBake ya puede limitar su fetcher a una lista de hosts con BB_ALLOWED_NETWORKS. CRACI añade un segundo control en el runner: una política de salida que se comprueba antes de que empiece el job y bloquea ante cualquier fallo, de modo que una receta, un script o una herramienta comprometida que esquive el fetcher sigue sin poder llegar a un host que usted no haya permitido. CRACI le avisa de las infracciones de la política.
Un registro de lo que descargó el build
CRACI observa el tráfico que un job envía a los hosts de paquetes y de código fuente, y lo registra como evidencia del build. Para un build de Yocto, eso supone un registro independiente de las fuentes que llegaron realmente por la red, junto a la SBOM que escribe el propio Yocto.
Un workflow mínimo
El ejemplo de Yocto de la documentación de CRACI compila core-image-sato para qemux86-64. Lo que importa para CRACI es el tamaño del runner y una configuración del fetcher que use el mirror oficial de fuentes de 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 La guía de la documentación incluye el workflow completo, con las dependencias del host y la configuración regional, y la referencia de configuración del runner enumera todas las opciones de configuración.
Lo que conviene saber
- Los builds se ejecutan desde GitHub Actions en los runners gestionados de CRACI, sobre infraestructura europea. Los runners alojados por el cliente y otros sistemas de CI están en la hoja de ruta.
- Apunte BitBake a mirrors que CRACI pueda ver, como el mirror oficial de fuentes de Yocto, en lugar de a hosts arbitrarios. La guía de la documentación muestra una configuración que funciona.
- Conservar el directorio de descargas y la caché de shared state entre ejecuciones es lo que hace rápidos los builds repetidos.
- Los runners ARM64 nativos están disponibles a la misma tarifa que los x86-64.
¿Desarrolla dispositivos conectados para el mercado de la UE? Lea qué exige el CRA y cómo funciona CRACI para IoT industrial y electrónica de consumo. ¿Compara herramientas de SBOM para Yocto? Consulte CRACI frente a Timesys Vigiles.
SBOM de Yocto y CRACI: preguntas frecuentes
¿Genera Yocto una SBOM?
Sí. El sistema de build OpenEmbedded genera por defecto una SBOM en SPDX desde Yocto 4.3 (Nanbield), mediante la clase create-spdx. Para una imagen escribe IMAGE-MACHINE.spdx.json en tmp/deploy/images/MACHINE/, con componentes, licencias, dependencias, fuentes, parches aplicados y vulnerabilidades corregidas. En Kirkstone (4.0), añada INHERIT += "create-spdx" para activarla.
¿Qué versión de SPDX genera Yocto?
SPDX 3.0 por defecto desde Yocto 5.1 (Styhead), que sustituyó a la 2.2 como versión por defecto. Scarthgap (5.0) genera SPDX 2.2 por defecto y puede pasar a 3.0 con la clase create-spdx-3.0.
¿Cómo obtengo una SBOM en CycloneDX desde Yocto?
Añada la capa meta-cyclonedx en la rama correspondiente a su versión y herede cyclonedx-export en local.conf. Escribe una SBOM .cyclonedx.bom.json y un archivo .cyclonedx.vex.json junto a la imagen, en CycloneDX 1.6 por defecto.
¿Qué se le escapa a la SBOM de Yocto?
En un build comparativo de core-image-sato, la SBOM registrada por CRACI tenía los 865 componentes de la SBOM de Yocto y 88 más: paquetes del host en la máquina de build, como cpio de Ubuntu, fuentes y Actions de GitHub, y otras fuentes descargadas durante el build. Además, Yocto enumera sus 653 versiones de crates de Rust solo por nombre de archivo y URL de descarga, sin package URL, que es en lo que se basa el cotejo de vulnerabilidades.
¿Puedo monitorizar vulnerabilidades en un build de Yocto?
Sí, con CRACI. El cotejo de vulnerabilidades funciona con package URLs, y la SBOM integrada de Yocto enumera los crates de Rust solo por nombre de archivo y URL de descarga, así que no se pueden cotejar. CRACI registra los crates de Rust y los paquetes de la máquina de build con los package URLs con los que se publican los avisos (pkg:cargo, pkg:deb), incluidas las 653 versiones de crates de core-image-sato. Muestra el estado de vulnerabilidad de cada paquete y sigue reevaluando la SBOM a medida que se publican nuevos avisos.
¿Puede CRACI sustituir la SBOM de Yocto?
En cobertura de la cadena de suministro, sí. En la misma comparativa, la SBOM de CRACI tenía todos los componentes de la SBOM integrada de Yocto, 88 más y un package URL para cada crate de Rust, y el build sin la generación de SBOM de Yocto tardó un 43% menos. La salida SPDX de Yocto sigue incluyendo metadatos de las recetas que CRACI no registra, como los parches aplicados y las CVE que una receta marca como corregidas. Si depende de ellos, mantenga create-spdx activado.
¿Puede un runner de CRACI encargarse del build completo de una imagen Yocto?
Los runners de CRACI llegan hasta 32 vCPU y 96 GB de RAM, y el tamaño se define desde el workflow. La documentación de CRACI incluye un ejemplo de Yocto que compila core-image-sato en el tamaño más grande.
¿Qué CI utiliza un build de Yocto en CRACI?
GitHub Actions. Su workflow se ejecuta en los runners gestionados de CRACI y las ejecuciones aparecen en GitHub como cualquier otro job de Actions. Otros sistemas de CI y los runners alojados por el cliente están en la hoja de ruta.
Traiga un build de Yocto a la demo
Reserve una demo: ejecutaremos uno de sus builds de BitBake en un runner de CRACI y repasaremos con usted lo que descargó.
Reservar una demo