⏱️ Lectura: 16 min
En mayo de 2021, la Casa Blanca firmó la Orden Ejecutiva 14028 tras el ataque a la cadena de suministro de SolarWinds. Esa orden convirtió al SBOM (software bill of materials) en un requisito legal para todo proveedor de software del gobierno de EE.UU. Siete meses después, cuando CVE-2021-44228 (Log4Shell) expuso a medio internet, esa misma exigencia marcó la diferencia entre responder en minutos o tardar semanas.
📑 En este artículo
- TL;DR
- Qué es un SBOM y por qué importa
- Cómo funciona un SBOM por dentro
- Ejemplos prácticos
- Cómo empezar: instalar y generar tu primer SBOM
- Casos de uso reales
- Errores comunes y buenas prácticas
- Comparativa con alternativas
- Profundizando
- Preguntas frecuentes
- ¿Un SBOM reemplaza un escáner de vulnerabilidades?
- ¿SPDX o CycloneDX, cuál elegir si no tengo un requisito externo?
- ¿Hace falta generar el SBOM en cada build o alcanza con hacerlo una vez al mes?
- ¿Un SBOM sirve para código propio, o solo para dependencias de terceros?
- ¿Qué pasa si una dependencia no tiene un purl reconocible?
- Referencias
Un SBOM resuelve un problema muy concreto: es un inventario exacto y legible por máquina de cada componente, versión y licencia que compone una pieza de software, generado automáticamente en cada build. Vas a aprender cómo generarlo con herramientas open source como Syft, cómo escanearlo con Grype y cómo automatizarlo en un pipeline de CI/CD.
TL;DR
- Vas a entender qué es un SBOM y por qué la Orden Ejecutiva 14028 lo volvió obligatorio en EE.UU. desde 2021.
- Vas a diferenciar los formatos SPDX y CycloneDX y saber cuándo usar cada uno.
- Vas a generar tu primer SBOM real con Syft en menos de un minuto, sin cuenta ni configuración previa.
- Vas a escanear ese SBOM con Grype para detectar CVEs conocidos como Log4Shell antes de que te afecten.
- Vas a automatizar la generación y el escaneo del SBOM en un pipeline de GitHub Actions.
- Vas a distinguir un SBOM estático de build de uno dinámico de runtime, y cuándo necesitás cada uno.
- Vas a conocer los errores que vuelven un SBOM inútil el día de un incidente real.
Qué es un SBOM y por qué importa
Un SBOM es, en esencia, la lista de ingredientes de tu software. Así como una etiqueta alimentaria declara cada componente de un producto, un SBOM declara cada librería, versión y licencia que entra en un binario, una imagen de contenedor o un paquete. La diferencia con un archivo package.json o un requirements.txt es que el SBOM incluye también las dependencias transitivas y se genera en un formato estándar que cualquier herramienta puede leer.
La necesidad no es teórica. El ataque a SolarWinds en diciembre de 2020 comprometió una actualización de software que llegó a cerca de 18.000 organizaciones, incluidas varias agencias federales de EE.UU. La mayoría de las víctimas no sabía qué versión del componente afectado corría en su propia infraestructura. Un año después, Log4Shell repitió el problema a otra escala: una librería de logging tan común que estaba enterrada tres o cuatro niveles debajo de miles de aplicaciones, y casi nadie tenía un inventario que la mencionara explícitamente.
En 2026 la lista de incidentes de cadena de suministro de software sigue creciendo: paquetes maliciosos en npm y PyPI, herramientas de escaneo comprometidas, credenciales robadas desde dependencias de terceros. Ese patrón repetido es la razón por la que reguladores y equipos de seguridad dejaron de tratar el SBOM como un ejercicio de cumplimiento y empezaron a tratarlo como infraestructura operativa: el inventario que responde en minutos la pregunta que antes tomaba días.
Cómo funciona un SBOM por dentro
Un SBOM no es un formato único: existen dos estándares dominantes, SPDX y CycloneDX, y ambos representan lo mismo con estructuras distintas. SPDX nació en la Linux Foundation con foco en licencias de software y se convirtió en el estándar ISO/IEC 5962:2021. CycloneDX nació dentro del proyecto OWASP con foco en seguridad de la cadena de suministro y hoy soporta de forma nativa VEX (Vulnerability Exploitability eXchange), un mecanismo para declarar si una vulnerabilidad conocida realmente afecta a tu producto.
Los dos formatos modelan el mismo concepto central: un componente tiene un nombre, una versión y un identificador único llamado purl (package URL), como pkg:maven/org.apache.logging.log4j/[email protected]. El mismo esquema identifica paquetes de otros ecosistemas: pkg:npm/[email protected] para npm o pkg:pypi/[email protected] para Python. Esa uniformidad es lo que permite que una sola base de datos de vulnerabilidades, como la del NVD, cruce automáticamente inventarios que mezclan varios lenguajes en un mismo proyecto.
| Formato | Cuándo usarlo | Ventaja | Limitación |
|---|---|---|---|
| SPDX | Cumplimiento legal y de licencias, contratos con el sector público | Estándar ISO/IEC 5962:2021, modela licencias en detalle | Sintaxis más verbosa para representar vulnerabilidades |
| CycloneDX | Seguridad de la cadena de suministro, integración con escáneres de CVE | Soporta VEX de forma nativa y es más liviano de generar en CI | Menos foco en metadatos complejos de licencias |
La mayoría de las herramientas modernas, incluida Syft, generan ambos formatos con la misma línea de comando. La elección suele depender de qué exige tu cliente o regulador, no de una limitación técnica.
flowchart LR
A["checkout-api 2.4.1"] --> B["spring-boot 3.2.0"]
A --> C["log4j-core 2.14.1"]
B --> D["jackson-databind 2.15.2"]
C --> E["log4j-api 2.14.1"]
subgraph "Dependencias transitivas"
D
E
end
Ese diagrama es exactamente el problema que resuelve un SBOM: log4j-core puede no aparecer nunca en tu pom.xml directo, sino colgar tres niveles abajo de una dependencia que sí declaraste. Sin un inventario del árbol completo, esa librería es invisible hasta que alguien pregunta específicamente por ella.
💭 Clave: el purl es el identificador que conecta tu SBOM con bases de vulnerabilidades. Sin un purl consistente, cruzar el inventario contra CVEs conocidos se vuelve manual.
Ejemplos prácticos
La forma más simple de ver un SBOM en acción es generarlo. Syft es una herramienta open source de Anchore que soporta más de 20 ecosistemas de paquetes (npm, pip, Maven, Go modules, gems, APK de Alpine, RPM, y más) y produce salida en SPDX o CycloneDX con un solo comando.
syft dir:. -o cyclonedx-json > sbom.json
Ese comando escanea el directorio actual, detecta cada manifiesto de dependencias que encuentra (package-lock.json, go.sum, Pipfile.lock, etcétera) y escribe un SBOM en formato CycloneDX JSON. El resultado tiene esta forma:
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"components": [
{
"type": "library",
"name": "log4j-core",
"version": "2.14.1",
"purl": "pkg:maven/org.apache.logging.log4j/[email protected]"
}
]
}
Ese fragmento es, literalmente, una entrada del inventario: una librería llamada log4j-core, versión 2.14.1, identificada por su purl. Multiplicá esa entrada por cada componente del proyecto (en una aplicación real fácilmente son cientos, contando las transitivas) y tenés el SBOM completo.
El siguiente paso es cruzar ese archivo contra una base de vulnerabilidades. Grype, del mismo equipo que Syft, lee directamente la salida de Syft:
syft packages registry:ghcr.io/acme/checkout-api:2.4.1 -o spdx-json > checkout-api.spdx.json
grype sbom:checkout-api.spdx.json --fail-on high
La primera línea genera el SBOM directamente desde una imagen de contenedor en un registro remoto, sin descargarla manualmente. La segunda escanea ese SBOM y devuelve un código de salida distinto de cero si encuentra una vulnerabilidad de severidad alta o crítica, útil para cortar un pipeline de CI antes de publicar una imagen vulnerable.
Cómo empezar: instalar y generar tu primer SBOM
Instalar Syft y Grype toma menos de un minuto en Linux o macOS:
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
Para confirmar que la instalación funcionó y ver la versión exacta instalada:
syft version
grype version
Con ambas herramientas listas, el flujo mínimo es: generar el SBOM del código o de la imagen, escanearlo y decidir si el resultado bloquea el build. La acción oficial de Anchore hace ambos pasos en GitHub Actions:
name: sbom
on: [push]
jobs:
generate-sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Generar SBOM con Syft
uses: anchore/sbom-action@v0
with:
path: .
format: cyclonedx-json
output-file: sbom.cdx.json
- name: Escanear con Grype
uses: anchore/scan-action@v3
with:
sbom: sbom.cdx.json
fail-build: true
severity-cutoff: high
Ese pipeline corre en cada push, genera el SBOM, lo escanea y falla el build si aparece algo de severidad alta o crítica. Para verificar que el archivo generado tiene contenido real, un chequeo simple con jq cuenta los componentes:
jq '.components | length' sbom.cdx.json
Si ese número es 0 o sospechosamente bajo comparado con el tamaño real del proyecto, algo en la detección de manifiestos falló antes de confiar en el resultado del escaneo.
💡 Tip: corré syft dir:. -o table la primera vez en lugar de JSON. El formato tabla es mucho más fácil de leer para verificar a ojo que Syft detectó todos los manifiestos esperados antes de automatizar nada.
Casos de uso reales
El caso de uso más citado es la respuesta a incidentes. Cuando aparece un CVE nuevo en una librería popular, un equipo con SBOMs centralizados responde la pregunta “¿dónde corre esto?” con una consulta, no con una auditoría manual proyecto por proyecto.
sequenceDiagram
participant Eq as Equipo de seguridad
participant Reg as Registro central de SBOMs
participant Sist as Sistemas en producción
Eq->>Reg: busca "log4j-core 2.14.1" en todos los SBOM
Reg-->>Eq: devuelve los sistemas que la contienen
Eq->>Sist: aplica el parche solo donde aplica
Note over Eq,Sist: sin SBOM, esta búsqueda toma días de auditoría manual
Otro caso de uso es contractual: desde la Orden Ejecutiva 14028, cualquier proveedor que le venda software al gobierno federal de EE.UU. debe poder entregar un SBOM bajo pedido. Empresas privadas grandes empezaron a exigir lo mismo a sus proveedores, por la misma razón que exigen un certificado de origen a un proveedor de hardware.
Un tercer caso, menos discutido, es el de licencias: un SBOM en formato SPDX permite a un equipo legal auditar automáticamente si alguna dependencia trajo una licencia copyleft incompatible con un producto propietario, sin depender de que un desarrollador la haya declarado a mano.
Un cuarto caso, cada vez más común, aparece en fusiones y adquisiciones: antes de comprar una empresa de software, el equipo de due diligence técnico pide el SBOM completo del producto para evaluar el riesgo de licencias y vulnerabilidades heredadas antes de firmar.
Errores comunes y buenas prácticas
El error más común es generar el SBOM una sola vez, al lanzar el proyecto, y no volver a actualizarlo. Un SBOM desactualizado es peor que no tener SBOM: da una falsa sensación de cobertura mientras el árbol de dependencias real ya cambió. La práctica correcta es generarlo en cada build, como parte del pipeline de CI.
El segundo error es escanear solo las dependencias directas. La mayoría de las vulnerabilidades explotadas en la práctica, incluida Log4Shell, viven en dependencias transitivas que nadie declaró a mano. Un SBOM generado con Syft resuelve esto porque recorre el árbol completo. Si el equipo arma el inventario manualmente a partir del manifiesto de primer nivel, se pierde justamente lo que más importa.
El tercer error es tratar cada resultado de Grype como una alerta urgente sin revisar si la vulnerabilidad es explotable en el contexto real de la aplicación. Muchas veces una librería vulnerable está presente pero la función afectada nunca se llama. Ahí es donde entra VEX: declarar explícitamente que una vulnerabilidad conocida no aplica evita que el equipo pierda horas revisando falsos positivos cada semana.
El cuarto error es olvidar los componentes que no son paquetes de un gestor tradicional: la imagen base del contenedor, los paquetes del sistema operativo instalados con apt o apk, binarios compilados a mano. Syft también los detecta, pero solo si se le apunta a la imagen final y no únicamente al código fuente del repositorio.
⚠️ Ojo: un SBOM generado a partir del código fuente puede no coincidir con lo que realmente corre en producción, si el proceso de build agrega o reemplaza dependencias en tiempo de deploy. Generá el SBOM lo más cerca posible del artefacto final, la imagen de contenedor, no el repositorio.
Comparativa con alternativas
Syft y Grype no son la única combinación posible. La elección depende de si ya tenés un escáner de contenedores instalado o si preferís herramientas separadas para generar y para escanear.
| Herramienta | Cuándo usarla | Ventaja | Limitación |
|---|---|---|---|
| Syft | Generar el SBOM inicial de un repo, imagen o directorio | Soporta SPDX y CycloneDX en más de 20 ecosistemas de paquetes | No escanea vulnerabilidades por sí solo |
| Grype | Escanear un SBOM existente contra bases de CVE | Se integra directo con la salida de Syft sin conversión | Depende de que la base de datos de vulnerabilidades esté actualizada |
| Trivy | Un solo comando para generar y escanear a la vez | Cubre además configuración de infraestructura como código y secretos expuestos | El SBOM que genera es menos configurable que el de Syft |
| sbom-tool (Microsoft) | Organizaciones que ya operan sobre Azure DevOps | Integración nativa con ese pipeline | Menor adopción fuera del ecosistema Microsoft |
En equipos que ya usan Trivy para escanear imágenes de contenedor, sumar Syft y Grype puede ser redundante. La combinación tiene sentido cuando se necesita separar explícitamente el paso de generar el inventario del paso de decidir qué hacer con él, por ejemplo para archivar el SBOM independientemente del resultado del escaneo.
Profundizando
Un SBOM generado a partir del código fuente es un SBOM estático: describe lo que el build declara, no necesariamente lo que corre en memoria. Un SBOM dinámico se genera inspeccionando un proceso en ejecución y captura dependencias cargadas dinámicamente que un análisis estático puede no ver, como plugins cargados en tiempo de ejecución. Los dos son complementarios: el estático es barato de generar en cada build, el dinámico es más caro pero más fiel a la realidad de producción.
El otro concepto avanzado es VEX (Vulnerability Exploitability eXchange). Un escaneo de SBOM contra una base de CVEs produce, casi siempre, una lista larga de coincidencias por versión de paquete, sin importar si el código vulnerable realmente se ejecuta. VEX es un documento separado, en formato CycloneDX o CSAF, donde el mantenedor de un producto declara el estado de cada CVE: affected, not_affected, fixed o under_investigation. Combinar SBOM más VEX es lo que reduce la fatiga de falsos positivos que sufre cualquier equipo que empieza a escanear en serio.
En la práctica, un proyecto Node.js mediano puede fácilmente superar varios cientos de dependencias contando las transitivas, la gran mayoría nunca revisadas manualmente por nadie del equipo. Ese es el tamaño real del problema que un SBOM hace visible: no es una lista de diez librerías que el equipo recuerda de memoria, es un grafo que ninguna persona puede mantener actualizado a mano.
Por último, un SBOM sin firma es solo un archivo más que alguien podría reemplazar. El proyecto Sigstore permite firmar el SBOM en el mismo paso del pipeline donde se genera, de forma que cualquiera pueda verificar que ese inventario específico corresponde exactamente a esa build y no fue alterado después.
📖 Resumen en Telegram: Ver resumen
Tu próximo paso: corré syft dir:. -o table sobre un repositorio real que tengas a mano y contá cuántas dependencias transitivas aparecen que no reconocías.
Preguntas frecuentes
¿Un SBOM reemplaza un escáner de vulnerabilidades?
No. El SBOM es el inventario; el escáner, como Grype, es lo que cruza ese inventario contra una base de datos de CVEs conocidos. Sin el SBOM, el escáner no tiene un mapa completo de qué buscar, especialmente en dependencias transitivas.
¿SPDX o CycloneDX, cuál elegir si no tengo un requisito externo?
Si el objetivo principal es seguridad y escaneo de vulnerabilidades, CycloneDX suele ser más directo por su soporte nativo de VEX. Si el objetivo es cumplimiento de licencias, SPDX modela ese dominio con más detalle.
¿Hace falta generar el SBOM en cada build o alcanza con hacerlo una vez al mes?
Generarlo en cada build es la práctica recomendada. Las dependencias cambian con cada actualización de una librería, y un SBOM desactualizado por semanas puede omitir justo la versión vulnerable que se agregó ayer.
¿Un SBOM sirve para código propio, o solo para dependencias de terceros?
Principalmente para terceros, que es donde vive el riesgo de la cadena de suministro. Herramientas como Syft también listan el componente principal del proyecto, pero el valor real está en mapear todo lo que no escribiste vos.
¿Qué pasa si una dependencia no tiene un purl reconocible?
Sigue apareciendo en el SBOM con la metadata disponible: nombre, versión, ubicación en el árbol. Pero cruzarla automáticamente contra bases de CVE se vuelve menos confiable, y es un buen indicador de que esa dependencia merece revisión manual.
Referencias
- CycloneDX: especificación oficial del formato y ejemplos de esquema.
- SPDX: especificación oficial del estándar ISO/IEC 5962:2021.
- Syft en GitHub: código fuente, documentación de instalación y ecosistemas soportados.
- Grype en GitHub: documentación del escáner de vulnerabilidades sobre SBOM.
- Software bill of materials en Wikipedia: contexto histórico y adopción regulatoria.
- CISA: agencia de EE.UU. que impulsa la adopción de SBOM tras la Orden Ejecutiva 14028.
📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.
Imagen destacada: Foto de Artturi Jalli en Unsplash
0 Comentarios