Yocto
SBOM Yocto et builds sur CRACI
Yocto peut écrire une SBOM SPDX détaillée pour chaque image. Lors d'un build comparatif, la SBOM enregistrée par CRACI contenait tous les composants de celle de Yocto, plus 88 absents de celle-ci, et une package URL pour chacune des 653 crates Rust que Yocto liste sans en fournir, avec un temps de build inférieur de 43 %.
Mis à jour le
Construits côte à côte : core-image-sato
Comment générer une SBOM avec Yocto
Le système de build OpenEmbedded écrit des SBOM SPDX via la classe create-spdx. Son activation, et la version de SPDX qu'il écrit, dépendent de la release Yocto :
- Kirkstone (4.0) : désactivée par défaut. Ajoutez
INHERIT += "create-spdx". SPDX 2.2. - Nanbield (4.3) : la génération de SBOM est activée par défaut à partir de cette release.
- Scarthgap (5.0) : activée par défaut, SPDX 2.2. SPDX 3.0 est disponible via la classe
create-spdx-3.0. - Styhead (5.1) et suivantes : activée par défaut, SPDX 3.0.
Le réglage se fait dans un fichier de configuration comme conf/local.conf. Sur une release récente, il n'y a généralement rien à ajouter ; pour la désactiver, utilisez 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" D'autres variables SPDX_ ajoutent des détails. SPDX_INCLUDE_SOURCES décrit les fichiers source derrière chaque outil hôte et chaque paquet cible, ce qui alourdit fortement la sortie. Les releases récentes ajoutent des options pour la configuration du noyau, les fonctionnalités PACKAGECONFIG, les informations sur les fournisseurs et les package URL des sources Cargo, Go, PyPI, npm et CPAN.
Où se trouvent les fichiers SBOM
Construisez une image et la SBOM de premier niveau apparaît à côté, sous le nom IMAGE-MACHINE.spdx.json dans tmp/deploy/images/MACHINE/, à l'intérieur du répertoire de build. Les fichiers associés se trouvent dans le même répertoire et dans tmp/deploy/spdx. Sur Kirkstone, les documents par recette sont fournis dans une archive 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 avec meta-cyclonedx
Yocto lui-même n'écrit que du SPDX. Pour CycloneDX, la couche meta-cyclonedx génère une SBOM à partir du système de fichiers racine de l'image, plus un fichier VEX distinct avec les CVE corrigées et ignorées que connaît le système de build. Récupérez la branche de la couche correspondant à votre release, ajoutez-la à vos couches et héritez de sa 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" Les fichiers sont déposés à côté de l'image dans DEPLOY_DIR_IMAGE, avec les suffixes .cyclonedx.bom.json et .cyclonedx.vex.json. La version par défaut est CycloneDX 1.6, réglable avec CYCLONEDX_SPEC_VERSION. Par défaut, seuls les paquets d'exécution sont inclus, ce qui garde la SBOM compacte mais peut laisser de côté des composants qui arrivent dans l'image sans être installés comme paquets.
Ce que la SBOM Yocto laisse de côté
La SBOM de Yocto est exhaustive sur ce que BitBake construit. En SPDX 3, elle couvre l'image, chaque recette y compris les recettes natives utilisées au build, leurs sources, les patches appliqués et les vulnérabilités marquées comme corrigées. Pour core-image-sato, cela représentait 1,632 fichiers distincts. Pour voir ce qu'elle laisse de côté, nous avons construit l'image sur un runner CRACI, en ARM64 natif avec 32 vCPU, et comparé la SBOM de Yocto à celle enregistrée par CRACI, composant par composant, après avoir normalisé les noms dans l'ensemble de ces fichiers.
Sur 953 composants dans la SBOM de CRACI, 865 figuraient aussi dans celle de Yocto. Aucun ne figurait uniquement dans celle de Yocto. Les différences tiennent à ce que Yocto ne peut pas voir, et à la façon dont il identifie ce qu'il liste.
Des crates Rust sans package URL
Les deux SBOM contiennent les mêmes 653 versions de 559 crates Rust, comme cairo-rs et zune-jpeg, que librsvg compile. Yocto liste chacune uniquement comme un fichier .crate et une URL de téléchargement crates.io, à l'intérieur de la recette qui l'utilise. Aucune ne porte de package URL pkg:cargo. CRACI enregistre chaque crate avec la sienne.
C'est ce qui détermine si vous pouvez surveiller leurs vulnérabilités. La détection des vulnérabilités repose sur les package URL : un avis concernant une crate la désigne par pkg:cargo/..., et un nom de fichier dans la liste des sources d'une autre recette ne donne aux outils SBOM et de vulnérabilités rien à quoi la rapprocher. Avec la seule SBOM de Yocto, une crate vulnérable dans votre image passe inaperçue.
Avec celle de CRACI, chaque crate est confrontée aux avis de sécurité, chaque paquet du build affiche son statut de vulnérabilité, et CRACI réévalue la SBOM en continu à mesure que de nouveaux avis sont publiés, longtemps après la fin du build.
Ce que seul CRACI a trouvé
Les 88 composants absents de la SBOM de Yocto provenaient de l'extérieur des métadonnées de BitBake :
- 23 paquets de l'hôte installés sur la machine de build, comme
cpio2.15 d'Ubuntu,libc6,localesetpython3-jinja2. BitBake s'exécute avec eux, et la SBOM de Yocto ne les liste pas. - 10 sources GitHub, dont
patchelf,btrfs-progset la GitHub Actionactions/upload-artifact, épinglées au commit exécuté par le workflow - D'autres sources et outils récupérés pendant le build, comme
pseudo-prebuilt,tzdataet des outils de build Python tels quehatchlingetsetuptools_scm
Aucun d'eux n'est installé dans l'image, mais tous se trouvent sur le chemin critique du build : un outil hôte ou une Action compromis peut compromettre votre image sans jamais en faire partie. CRACI les liste parce qu'il voit le trafic qui entre dans le build.
Ce que coûte la SBOM intégrée
La génération de SBOM de Yocto n'est pas gratuite. Sur le même runner de 32 vCPU, le build qui l'incluait a pris 155 min 40 s et a écrit la SBOM sous forme de 1,632 fichiers SPDX distincts. Le build sans elle, avec l'enregistrement de CRACI, a pris 88 min 48 s. Au tarif CRACI de $0.002 par minute vCPU, cela représente environ $9.96 contre $5.68 par build, sans compter le temps que votre équipe passe à attendre.
L'écart se creuse face aux runners hébergés par GitHub. CRACI exécute les builds environ deux fois plus vite, grâce à un matériel plus rapide, des files d'attente plus courtes et le cache : le même build avec la SBOM de Yocto sur un runner ARM64 à 32 cœurs hébergé par GitHub prendrait environ 5 h 11 min. À $0.050 la minute, cela fait $15.60. Le build CRACI coûte $5.68 : 64% de moins, soit environ 2,7 fois moins cher. Prix catalogue GitHub de septembre 2026 ; les minutes incluses ne couvrent pas les runners de grande taille.
La sortie SPDX de Yocto contient toutefois des éléments que CRACI n'enregistre pas, comme les patches qu'une recette applique et les CVE qu'elle marque comme corrigées. Si votre processus en dépend, laissez create-spdx activé et utilisez la SBOM de CRACI en complément. Sinon, la SBOM de CRACI couvre à elle seule tous les composants de celle de Yocto, et davantage.
Pourquoi c'est important pour la sécurité de la chaîne d'approvisionnement
Ce qui entre dans un build détermine ce qui en sort, que ce soit installé dans l'image ou non. Les attaquants le savent, et c'est par le build que sont passées les récentes attaques de la chaîne d'approvisionnement :
- Les attaques se cachent dans le build. La backdoor de xz utils (CVE-2024-3094) se trouvait dans les versions 5.6.0 et 5.6.1. Son déclencheur était placé dans les tarballs de release plutôt que dans le dépôt Git, et le code malveillant s'est inséré dans la bibliothèque pendant son build. La lecture du code source ne la révélait pas ; savoir exactement quel tarball le build a récupéré, si.
- Les dépendances de la CI sont aussi des cibles. En mars 2025, la CISA a signalé que toutes les versions de la GitHub Action
tj-actions/changed-filesavaient été compromises pendant trois jours. Une Action s'exécute à l'intérieur de votre job de build : c'est pourquoi CRACI liste celles qu'utilise votre workflow, épinglées au commit exécuté. - Les crates Rust disparaissent dans les binaires. Cargo compile les crates dans les programmes qui les utilisent : une crate vulnérable est livrée dans l'image sans jamais apparaître comme un paquet. Si la SBOM ne la liste que par nom de fichier, les outils de vulnérabilités ne peuvent pas non plus la détecter. Scanner le binaire final après coup oblige à deviner ce qui y est entré ; enregistrer le build, non.
- On ne peut pas réagir à ce qu'on ne voit pas. Quand un avis de sécurité tombe pour une crate ou un outil de build, vous devez savoir quels builds l'ont utilisé. CRACI conserve la SBOM de chaque build et montre quels builds contenaient la dépendance vulnérable, directe ou transitive : vous connaissez la période pendant laquelle vous étiez touché. Cela ne fonctionne que si chaque composant a une package URL sur laquelle s'appuyer.
- Un build ne devrait atteindre que ce dont il a besoin. La politique de trafic sortant de CRACI bloque les connexions vers les hôtes dont le build n'a pas besoin : une dépendance compromise qui tente d'envoyer vos secrets vers le serveur d'un attaquant est arrêtée, même lors d'une attaque que personne n'a encore vue.
Les clients et des réglementations comme le Cyber Resilience Act demandent aussi aux fabricants d'appareils connectés de savoir ce qui entre dans leurs produits. Une SBOM qui couvre l'ensemble du build est une preuve qui tient la route lorsqu'ils posent la question.
Obtenez la comparaison complète
Les listes de composants derrière ces chiffres, les deux SBOM, et la façon dont nous les avons construites et comparées.
- Les 88 composants trouvés uniquement par CRACI, et les 865 listés par les deux SBOM
- La façon dont chaque SBOM identifie les 653 versions de crates Rust
- Les deux fichiers SBOM : le CycloneDX de CRACI et le SPDX de Yocto
- La configuration du build, la taille du runner et les temps mesurés
Merci, voici le rapport complet
Pourquoi les builds Yocto sont difficiles à exécuter en CI
Un build d'image complet compile une toolchain, un noyau et des centaines de paquets à partir des sources. Sur les runners standard à 2 cœurs que proposent la plupart des services de CI, cela peut prendre des heures : beaucoup d'équipes de l'embarqué gardent donc un serveur de build dédié sous un bureau ou dans une baie, et ce serveur devient une machine de plus à patcher, sauvegarder et justifier auprès d'un auditeur.
Un build Yocto télécharge aussi énormément : tarballs de sources, dépôts Git et patches issus des projets amont et de leurs miroirs. Ce sont ces téléchargements dont votre SBOM doit rendre compte, et que des réglementations comme le Cyber Resilience Act demandent aux fabricants d'appareils connectés de connaître et de suivre.
Ce que CRACI apporte à un build Yocto
Des runners dimensionnés pour BitBake
Les runners CRACI vont de 1 à 32 unités de calcul, chaque unité correspondant à 1 vCPU et 3 Go de RAM. Un build Yocto peut demander la plus grande taille, 32 vCPU et 96 Go de RAM, depuis le workflow lui-même. Les jobs s'exécutent dans des machines virtuelles isolées et les exécutions apparaissent toujours dans GitHub comme n'importe quel autre job Actions.
Les minutes sont mesurées à la seconde et facturées par minute vCPU : un grand runner coûte plus cher à la minute et termine plus tôt. Consultez les tarifs en vigueur.
L'accès réseau, c'est vous qui décidez
BitBake peut déjà restreindre son fetcher à une liste d'hôtes avec BB_ALLOWED_NETWORKS. CRACI ajoute un second contrôle au niveau du runner : une politique de trafic sortant vérifiée avant le démarrage du job et qui bloque tout en cas d'échec. Une recette, un script ou un outil compromis qui contourne le fetcher ne peut donc toujours pas atteindre un hôte que vous n'avez pas autorisé. CRACI vous alerte en cas de violation de la politique.
Un enregistrement de ce que le build a récupéré
CRACI observe le trafic qu'un job envoie vers les hôtes de paquets et de sources, et l'enregistre comme preuve de build. Pour un build Yocto, cela signifie un relevé indépendant des sources réellement arrivées par le réseau, à côté de la SBOM que Yocto écrit lui-même.
Un workflow minimal
L'exemple Yocto de la documentation CRACI construit core-image-sato pour qemux86-64. Ce qui compte pour CRACI, c'est la taille du runner et une configuration du fetcher qui utilise le miroir de sources officiel 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 Le guide de la documentation contient le workflow complet, y compris les dépendances de l'hôte et la configuration des locales, et la référence de configuration des runners liste toutes les options de configuration.
À savoir
- Les builds s'exécutent sur les runners managés de CRACI, sur une infrastructure européenne, depuis GitHub Actions. Les runners hébergés par le client et les autres systèmes CI figurent sur la roadmap.
- Faites pointer BitBake vers des miroirs que CRACI peut voir, comme le miroir de sources officiel de Yocto, plutôt que vers des hôtes arbitraires. Le guide de la documentation présente une configuration fonctionnelle.
- Conserver le répertoire des téléchargements et le cache shared state d'une exécution à l'autre, c'est ce qui rend les builds suivants rapides.
- Les runners ARM64 natifs sont disponibles au même tarif que x86-64.
Vous concevez des appareils connectés pour le marché européen ? Lisez ce qu'exige le CRA, et découvrez comment CRACI fonctionne pour l'IoT industriel et l'électronique grand public. Vous comparez des outils SBOM pour Yocto ? Voir CRACI face à Timesys Vigiles.
SBOM Yocto et CRACI : questions fréquentes
Yocto génère-t-il une SBOM ?
Oui. Le système de build OpenEmbedded génère par défaut une SBOM SPDX depuis Yocto 4.3 (Nanbield), via la classe create-spdx. Pour une image, il écrit IMAGE-MACHINE.spdx.json dans tmp/deploy/images/MACHINE/, avec les composants, les licences, les dépendances, les sources, les patches appliqués et les vulnérabilités corrigées. Sur Kirkstone (4.0), ajoutez INHERIT += "create-spdx" pour l'activer.
Quelle version de SPDX Yocto produit-il ?
SPDX 3.0 par défaut depuis Yocto 5.1 (Styhead), qui a remplacé la 2.2 comme version par défaut. Scarthgap (5.0) produit SPDX 2.2 par défaut et peut passer à la 3.0 avec la classe create-spdx-3.0.
Comment obtenir une SBOM CycloneDX avec Yocto ?
Ajoutez la couche meta-cyclonedx sur la branche correspondant à votre release et héritez de cyclonedx-export dans local.conf. Elle écrit une SBOM .cyclonedx.bom.json et un fichier .cyclonedx.vex.json à côté de l'image, en CycloneDX 1.6 par défaut.
Que manque-t-il à la SBOM Yocto ?
Lors d'un build comparatif de core-image-sato, la SBOM enregistrée par CRACI contenait les 865 composants de la SBOM Yocto, plus 88 autres : des paquets de la machine de build comme cpio d'Ubuntu, des sources et des Actions GitHub, et d'autres sources récupérées pendant le build. Yocto ne liste par ailleurs ses 653 versions de crates Rust que par nom de fichier et URL de téléchargement, sans package URL, sur laquelle repose la détection des vulnérabilités.
Peut-on surveiller les vulnérabilités d'un build Yocto ?
Oui, avec CRACI. La détection des vulnérabilités s'appuie sur les package URL, et la SBOM intégrée de Yocto ne liste les crates Rust que par nom de fichier et URL de téléchargement : impossible de les rapprocher des avis. CRACI enregistre les crates Rust et les paquets de la machine de build avec les package URL sous lesquelles les avis sont publiés (pkg:cargo, pkg:deb), y compris les 653 versions de crates de core-image-sato. Il affiche le statut de vulnérabilité de chaque paquet et réévalue la SBOM en continu à mesure que de nouveaux avis sont publiés.
CRACI peut-il remplacer la SBOM Yocto ?
Pour la couverture de la chaîne d'approvisionnement, oui. Dans la même comparaison, la SBOM de CRACI contenait tous les composants de la SBOM intégrée de Yocto, 88 de plus et une package URL pour chaque crate Rust, et le build sans la génération de SBOM de Yocto a pris 43 % de temps en moins. La sortie SPDX de Yocto contient toutefois des métadonnées de recettes que CRACI n'enregistre pas, comme les patches appliqués et les CVE qu'une recette marque comme corrigées. Si vous en dépendez, laissez create-spdx activé.
Un runner CRACI peut-il gérer un build complet d'image Yocto ?
Les runners CRACI vont jusqu'à 32 vCPU et 96 Go de RAM, à définir depuis le workflow. La documentation CRACI inclut un exemple Yocto qui construit core-image-sato sur la plus grande taille.
Quelle CI utilise un build Yocto sur CRACI ?
GitHub Actions. Votre workflow s'exécute sur les runners managés de CRACI et les exécutions apparaissent dans GitHub comme n'importe quel autre job Actions. Les autres systèmes CI et les runners hébergés par le client figurent sur la roadmap.
Apportez un build Yocto à la démo
Réservez une démo : nous exécuterons l'un de vos builds BitBake sur un runner CRACI et passerons en revue ce qu'il a récupéré.
Réserver une démo