Boottrace

Cómo sacar el SBOM de tu firmware Linux: Yocto, Buildroot o una imagen que no has compilado tú

El CRA pide un inventario de componentes legible por máquina. Cómo generarlo según cómo se construye tu firmware, qué trae ya tu sistema de build y por qué un escáner sobre la imagen no basta.

El anexo I del Cyber Resilience Act pide a los fabricantes identificar y documentar los componentes de su producto, entre otras cosas con una lista de materiales de software (SBOM) en un formato habitual y legible por máquina que cubra, como mínimo, las dependencias de primer nivel (parte II, punto 1). No hace falta publicarla: forma parte de la documentación técnica (anexo VII) y la autoridad de vigilancia del mercado puede pedírtela de forma motivada.

Sin SBOM no puedes responder a la pregunta más básica de la gestión de vulnerabilidades: cuando sale una CVE nueva, ¿me afecta? Cómo se saca depende de cómo construyes el firmware. Hay tres casos.

Caso 1: compilas con Yocto

Buenas noticias: probablemente ya lo estás generando. La distribución de referencia de Yocto (Poky) hereda la clase create-spdx por defecto, y cada build de imagen deja el SBOM en tmp/deploy/images/<máquina>/, con los ficheros de cada receta en tmp/deploy/spdx/.

Lo que cambia es la versión de SPDX:

  • Scarthgap (5.0, LTS con soporte hasta abril de 2028): create-spdx es SPDX 2.2. SPDX 3.0 está disponible pero hay que activarlo.
  • Desde Styhead (5.1): create-spdx ya es SPDX 3.0.

Si estás en scarthgap y quieres SPDX 3.0, que es el que mejor recoge el estado de las vulnerabilidades, en local.conf o en la configuración de tu distro:

INHERIT_DISTRO:remove = "create-spdx"
INHERIT_DISTRO:append = " create-spdx-3.0"

Si tu distro no deriva de Poky (pasa con algunos BSP), comprueba que la clase está activa:

bitbake -e core-image-minimal | grep -E '^(INHERIT|INHERIT_DISTRO)='

Lo que el SBOM de Yocto sabe y un escáner no. Yocto aplica parches de seguridad sin cambiar la versión del paquete: un paquete con tres CVEs corregidas por parche sigue declarando la misma versión que sin ellas. El build sabe qué parches lleva cada receta, porque se nombran con la CVE o llevan una línea CVE: CVE-AAAA-NNNN en la cabecera, y lo vuelca en el SBOM:

  • En SPDX 2.2, las CVEs parcheadas van en un campo de texto de cada paquete.
  • En SPDX 3.0, van como relaciones VEX: “corregida”, “no afecta” (con justificación) o “sin corregir”. Por defecto (SPDX_INCLUDE_VEX = "current") incluye las que no están ya corregidas en la versión de origen.

Las CVEs que has valorado y descartado se declaran con CVE_STATUS en la receta, con un motivo, y en SPDX 3.0 también acaban en el SBOM, como “no afecta”. Ese es justo el tipo de evidencia que el CRA espera ver: no “cero CVEs”, sino “estas no son explotables, y por esto”.

Qué no cubre. El SBOM de Yocto describe recetas. Si una receta compila un binario Go o Rust que trae sus dependencias dentro (Docker y containerd son el ejemplo típico), esas bibliotecas internas no aparecen como componentes ni reciben los parches de Yocto. Para eso hace falta mirar la imagen, como en el caso 3.

Caso 2: compilas con Buildroot

Buildroot no instala base de datos de paquetes en el dispositivo, así que el inventario hay que sacarlo del build:

  • make show-info vuelca en JSON los paquetes de la configuración, con versión, licencia, CPE y parches.
  • Desde Buildroot 2025.02, utils/generate-cyclonedx lo convierte en un SBOM CycloneDX:
make show-info | utils/generate-cyclonedx > sbom.cdx.json

Las CVEs que hayas marcado con <PAQUETE>_IGNORE_CVES en el .mk salen en el SBOM como descartadas. Si estás en una versión anterior, make show-info existe desde la 2019.05 y el script solo usa la biblioteca estándar de Python: puedes probarlo en tu árbol, o convertir el JSON con un script propio. Cuanto más antigua la versión, menos datos trae show-info (el CPE, por ejemplo, no aparece hasta la 2021.02).

Para cruzarlo con vulnerabilidades, make pkg-stats consulta la base de datos del NVD y te da las CVEs por paquete.

make legal-info es otra cosa: recoge licencias y fuentes para cumplir con la GPL. Útil, pero no es un SBOM.

Caso 3: tienes la imagen, pero no el build

Pasa más de lo que parece: el firmware lo compiló el proveedor del módulo, un integrador que ya no está, o es una distribución tipo Debian que nadie reconstruye. El CRA no te exime: el fabricante responde de los componentes de terceros que integra y tiene que actuar con diligencia debida sobre ellos.

Lo primero es pedirle el SBOM al proveedor. Si tiene un build de Yocto o Buildroot, lo tiene o lo puede generar en minutos.

Si no, se puede reconstruir desde la imagen con Syft:

syft dir:./rootfs -o spdx-json > sbom.spdx.json

Funciona bien en estos casos:

  • Imágenes con gestor de paquetes que Syft entiende: Debian y Ubuntu (dpkg), las basadas en RPM y Alpine.
  • Binarios Go: llevan dentro la lista de módulos con los que se compilaron, y Syft la lee. Así aparecen las dependencias internas de Docker o de tus propios servicios.
  • Binarios conocidos: Syft identifica la versión de un catálogo de programas habituales (BusyBox, OpenSSL y otros) aunque no haya base de paquetes.

Y tiene límites que conviene conocer:

  • Syft no lee la base de paquetes de opkg (ipk), el formato de muchas imágenes Yocto. Y Buildroot no deja ninguna. En esos casos sale un inventario parcial: lo que reconoce por los binarios.
  • No sabe nada de parches. Ve la versión de un paquete y le asigna todas sus CVEs, aunque el fabricante las haya corregido. El resultado es una lista inflada de falsos positivos.
  • El kernel lo identifica por versión, sin configuración. Para saber qué CVEs del kernel te afectan de verdad hace falta el .config, porque muchas están en código que tu kernel no compila. Si está activo CONFIG_IKCONFIG_PROC, lo tienes en /proc/config.gz del dispositivo.

Lo que recomendamos

  1. Genera el SBOM en el build, no a mano y no una sola vez: en cada versión que publiques, guardado junto a la imagen. El CRA pide gestionar vulnerabilidades durante todo el periodo de soporte, y para eso necesitas el inventario de cada versión que hay en el campo.
  2. Cruza el SBOM del build con un escaneo de la imagen. El primero sabe de parches; el segundo ve lo que el build no declara (dependencias internas de binarios, ficheros añadidos a mano). Las diferencias entre los dos son, en sí mismas, un hallazgo.
  3. Documenta los descartes con CVE_STATUS en Yocto o _IGNORE_CVES en Buildroot, siempre con el motivo. Es tu VEX, y es lo que vas a enseñar cuando alguien pregunte.
  4. Guarda el .config del kernel de cada versión. Sin él, la lista de CVEs del kernel no se puede filtrar.

En nuestro Quick Scan hacemos exactamente ese cruce: nos envías la imagen (y el SBOM de Yocto si lo tienes), y en 48 horas laborables recibes el inventario, las vulnerabilidades que de verdad aplican a tu dispositivo, los descartes justificados y lo que falta frente al CRA. Si prefieres verlo antes con tu caso concreto, reserva 30 minutos.

¿Tu producto tiene que cumplir el CRA?

Empieza por un Quick Scan de 1.900 € o reserva 30 minutos para hablarlo.

← Todos los artículos