Saltar al contenido
folhas.io
secure by design para productos conectados· Artículos

Artículos

SBOM para firmware embebido: lo que pide el CRA y cómo se genera sin mentir

La lista de materiales de software que exige el CRA no se escribe a mano. Para firmware, la única SBOM creíble sale del sistema de build, y el escaneo de binarios sirve para lo que no construimos nosotros.

Publicado
Actualizado

Nota de actualización (23 oct 2026). La lista de elementos mínimos sigue ahora la versión final publicada por la CISA y sus socios el 29 jul 2026. Hemos añadido el límite del número de versión cuando hay correcciones sin versión nueva, con el caso de PHP de octubre de 2026.

El Cyber Resilience Act exige, en el Anexo I, Parte II, que el fabricante identifique y documente los componentes del producto, incluso mediante una SBOM en formato legible por máquina que cubra, como mínimo, las dependencias de primer nivel. La SBOM no tiene que ser pública: forma parte de la documentación técnica y se entrega a las autoridades de vigilancia del mercado cuando la solicitan.

Para una aplicación web, esto es trabajo de una tarde. Para firmware, es donde la mayoría de los fabricantes va a fallar, y a fallar de una forma específica: entregando una SBOM que parece completa y no lo es.

El problema del firmware

Una imagen de firmware embebido normalmente no lleva gestor de paquetes a bordo. No hay base de datos dpkg ni apk que un escáner pueda consultar. Cuando se apunta una herramienta de análisis de composición a un rootfs extraído, la cobertura depende de lo que sobrevivió a la compilación: firmas de binarios, banners de versión, strings. El resultado son lagunas grandes y silenciosas, porque la herramienta no sabe lo que no encontró.

La consecuencia práctica: una SBOM generada por escaneo de binario sobre firmware es un punto de partida, y no basta como documento de conformidad.

La regla que resuelve casi todo

La SBOM creíble sale del sistema de build, no del binario. El sistema de build es el único sitio que sabe exactamente qué entró en la imagen, con qué versión, con qué parches y con qué licencia.

Los tres ecosistemas dominantes ya lo hacen de forma nativa:

  • Yocto: la clase create-spdx está incluida por defecto vía INHERIT_DISTRO desde Kirkstone (4.0). Un build normal de la imagen produce un .spdx.json en el directorio de deploy, derivado de los mismos inputs que produjeron el binario. Para quien prefiera CycloneDX, la meta-layer meta-cyclonedx produce SBOM CycloneDX 1.6/1.7 con CPE y purl corregidos para una mejor correspondencia con el NVD.
  • Buildroot: make legal-info genera el manifiesto completo de paquetes, versiones y licencias; el conversor cyclonedx-buildroot lo transforma en CycloneDX JSON.
  • Zephyr: west spdx genera documentos SPDX 2.3 para la aplicación, el Zephyr, el build y las dependencias de módulos. Atención a la limitación documentada: los blobs binarios de proveedores y las bibliotecas fuera del árbol no entran; hay que añadirlos como componentes externos o documentarlos como lagunas.

¿Y lo que no construimos nosotros?

Aquí es donde el análisis de binarios tiene su lugar legítimo: el bootloader entregado por el proveedor del SoC, el blob de radio, la biblioteca precompilada de un socio. Para esos, una herramienta de composición binaria produce un documento que después se reconcilia con el manifiesto del build. El método son dos inventarios, uno de lo que controlamos y otro de lo que heredamos, fundidos en un solo documento, con las lagunas identificadas como tales.

Diagrama: el sistema de build genera la SBOM de lo que construimos; el escaneo de binario inventaría los componentes heredados; los dos se reconcilian en un único documento final, con las lagunas declaradas.
Dos inventarios, un documento: el build responde por lo que construimos, el escaneo por lo que heredamos.

Qué formato

Los dos formatos aceptados en la práctica son SPDX (norma ISO/IEC 5962) y CycloneDX (ECMA-424). La orientación técnica alemana BSI TR-03183-2, el documento más citado por auditores y organismos notificados en el contexto del CRA, recomienda CycloneDX 1.6+ o SPDX 3.0.1+. CycloneDX tiene un tipo de componente nativo firmware y soporte VEX integrado, lo que lo convierte en la elección natural para el flujo CRA; Yocto produce SPDX de forma nativa. La respuesta pragmática para quien usa Yocto: generar ambos.

Como referencia de contenido mínimo, los “minimum elements” norteamericanos siguen siendo el listón práctico. La versión final, publicada el 29 de julio de 2026 por la CISA con la NSA, el FBI y socios internacionales (entre ellos el BSI, la ANSSI y el NCSC-NL), sustituye a la de la NTIA de 2021. Por componente: productor del componente (el antiguo “proveedor”; la propia CISA advierte de que no equivale al “fabricante” del CRA), nombre, versión, identificadores (purl y/o CPE), relación de dependencia, hash (valor y algoritmo) y licencia. Sobre la propia SBOM: autor y firma del autor, fecha y hora, versión de la SBOM, formato y versión del formato, herramienta y versión de la herramienta, y contexto de generación (“antes del build”, “build”, “después del build”). Este último campo es la regla de este artículo en forma de dato: dice si la SBOM salió del build o de un escaneo de binario.

El campo que más vale es la versión: la correspondencia con vulnerabilidades es precisa hasta el número. “Usamos OpenSSL” no dice nada; “OpenSSL 3.0.11” dice exactamente qué advisories se aplican.

El número de versión tiene un límite conocido. Muchas distribuciones Linux, y sistemas de build como Yocto, aplican correcciones de seguridad como parches, sin cambiar la versión de origen del componente. En octubre de 2026, al corregir los fallos conocidos como PHP2Shell, el proyecto PHP publicó también correcciones mínimas para las ramas 7.4, 8.0 y 8.1, ya al final de su vida útil, como ramas en el repositorio de código, sin versión numerada ni tarball. En esos casos la versión por sí sola no dice si la corrección está aplicada. Por eso, la SBOM generada en el build debe registrar también los parches aplicados (el sistema de build sabe cuáles son), y el estado de cada vulnerabilidad en el producto se comunica en VEX: afectado, no afectado, corregido o en investigación. En el kernel Linux, los backports enredan también los intervalos de versiones afectadas de los registros CVE, como muestra el artículo 10.

La lista de productos posiblemente afectados que el NCSC-NL publicó para esos fallos es un ejemplo público del formato: documentos SPDX en los que el estado de cada entrada se deriva de relaciones VEX. El artículo 09 trata el caso desde el punto de vista de quien fabrica.

Qué significa esto para quien fabrica

Tres decisiones que tomamos en nuestro propio producto, y que recomendamos a cualquier equipo:

  1. Generación en el pipeline. La SBOM se genera en cada build con tag, se guarda junto al binario, y ningún humano la escribe ni la corrige a mano. Cuando algo está mal en la SBOM, se corrige la receta o la configuración del build, y el build siguiente ya sale bien.
  2. Conexión a la monitorización. Cargada en una herramienta de seguimiento de CVE (por ejemplo Dependency-Track), la SBOM se convierte en el sistema de alerta que alimenta la obligación de gestión de vulnerabilidades del propio CRA, y el detonante del proceso de notificación de 24h/72h.
  3. Lagunas declaradas. Un blob que no conseguimos descomponer entra en la SBOM en una línea propia, marcado como laguna. Ante una autoridad de vigilancia del mercado, esa marca es lo que muestra qué cubre el inventario y qué queda fuera.

Fuentes