SBOM
Ejemplos de SBOM
La forma más rápida de entender una SBOM es leer una. Aquí tiene la misma aplicación pequeña en CycloneDX y en SPDX, con lo que significa cada campo, cómo es una SBOM débil y cómo revisar la suya.
Actualizado el
La aplicación de estos ejemplos
Ambos archivos describen example-api 2.4.0, un servicio Node.js ilustrativo con una dependencia directa,
express. Express depende a su vez de accepts, de modo que los ejemplos también muestran una
dependencia transitiva. Una SBOM real de una aplicación Express enumera muchos más componentes, pero la estructura es
la misma.
Ejemplo de SBOM en CycloneDX
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"serialNumber": "urn:uuid:3e671687-395b-41f5-a30f-a58921a69b79",
"version": 1,
"metadata": {
"timestamp": "2026-10-30T09:00:00Z",
"lifecycles": [{ "phase": "build" }],
"tools": {
"components": [
{ "type": "application", "name": "example-sbom-tool", "version": "1.0.0" }
]
},
"component": {
"type": "application",
"bom-ref": "example-api",
"name": "example-api",
"version": "2.4.0"
}
},
"components": [
{
"type": "library",
"bom-ref": "pkg:npm/[email protected]",
"name": "express",
"version": "4.21.2",
"purl": "pkg:npm/[email protected]",
"licenses": [{ "license": { "id": "MIT" } }]
},
{
"type": "library",
"bom-ref": "pkg:npm/[email protected]",
"name": "accepts",
"version": "1.3.8",
"purl": "pkg:npm/[email protected]",
"licenses": [{ "license": { "id": "MIT" } }]
}
],
"dependencies": [
{ "ref": "example-api", "dependsOn": ["pkg:npm/[email protected]"] },
{ "ref": "pkg:npm/[email protected]", "dependsOn": ["pkg:npm/[email protected]"] }
]
}
| Campo | Qué le indica |
|---|---|
specVersion |
Qué versión del formato usa el archivo, para que las herramientas puedan analizarlo. |
serialNumber, version |
Qué SBOM es y de qué revisión se trata. |
metadata.lifecycles |
Cuándo se creó la SBOM. Aquí, durante el build. |
metadata.tools |
Qué herramienta la generó. Dos herramientas pueden informar de forma distinta sobre el mismo commit. |
metadata.component |
El producto que describe la SBOM. |
purl |
La package URL, el identificador que permite a una herramienta cotejar el componente con los avisos. |
licenses |
La licencia declarada del componente. |
dependencies |
Quién incorpora a quién. Esto es lo que hace visible accepts como dependencia transitiva. |
Ejemplo de SBOM en SPDX
{
"spdxVersion": "SPDX-2.3",
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "example-api-2.4.0",
"documentNamespace": "https://example.com/spdx/example-api-2.4.0",
"creationInfo": {
"created": "2026-10-30T09:00:00Z",
"creators": ["Tool: example-sbom-tool-1.0.0"]
},
"packages": [
{
"name": "example-api",
"SPDXID": "SPDXRef-Package-example-api",
"versionInfo": "2.4.0",
"downloadLocation": "NOASSERTION"
},
{
"name": "express",
"SPDXID": "SPDXRef-Package-express",
"versionInfo": "4.21.2",
"downloadLocation": "NOASSERTION",
"licenseDeclared": "MIT",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:npm/[email protected]"
}
]
},
{
"name": "accepts",
"SPDXID": "SPDXRef-Package-accepts",
"versionInfo": "1.3.8",
"downloadLocation": "NOASSERTION",
"licenseDeclared": "MIT",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceType": "purl",
"referenceLocator": "pkg:npm/[email protected]"
}
]
}
],
"relationships": [
{
"spdxElementId": "SPDXRef-DOCUMENT",
"relationshipType": "DESCRIBES",
"relatedSpdxElement": "SPDXRef-Package-example-api"
},
{
"spdxElementId": "SPDXRef-Package-example-api",
"relationshipType": "DEPENDS_ON",
"relatedSpdxElement": "SPDXRef-Package-express"
},
{
"spdxElementId": "SPDXRef-Package-express",
"relationshipType": "DEPENDS_ON",
"relatedSpdxElement": "SPDXRef-Package-accepts"
}
]
}
La información es la misma, organizada de otra manera. SPDX mantiene una lista packages y declara cada
vínculo entre elementos en relationships. licenseDeclared es lo que el paquete dice de sí
mismo, y downloadLocation puede ser NOASSERTION cuando la herramienta no lo sabe. Para ver en
qué se diferencian los dos formatos más allá de la estructura, consulte
CycloneDX frente a SPDX.
Cómo es una SBOM débil
Un archivo puede ser válido y aun así casi inútil. Preste atención a lo siguiente:
- Sin relaciones de dependencia. Una lista plana le dice que un paquete está presente, pero no qué lo incorporó, que es lo que necesita para corregir una dependencia transitiva.
- Sin package URLs. Sin un identificador como una purl, cotejar un componente con los avisos se reduce a hacer suposiciones a partir de los nombres.
-
Licencias ausentes. Muchos campos con
NOASSERTIONsignifican que la SBOM no puede responder a preguntas sobre licencias. - Sospechosamente pocos componentes. Un puñado de componentes para una aplicación grande suele significar que solo figuran las dependencias directas, o solo lo que declaraba un lockfile.
- Nada sobre cuándo ni cómo. Sin una herramienta y un contexto de generación, no puede saber hasta dónde cabe confiar en la cobertura de la SBOM.
- Silencio sobre las lagunas. Una buena SBOM indica lo que no pudo ver. La mayoría de los archivos simplemente terminan, y quien los lee da por hecho que están completos.
Cómo revisar su propia SBOM
- Valide el formato. Pásela por un validador de esquemas para su formato y versión, porque una herramienta que no puede analizar el archivo no puede usarlo.
- Compruebe los campos. Compárela con los 2026 Minimum Elements o con la lista que le haya pedido su cliente.
- Busque algo que conozca. Elija una dependencia transitiva, un paquete de su imagen base y una herramienta de build, y vea cuáles aparecen.
- Compare dos fuentes. Genere una segunda SBOM con otro método y observe la diferencia. Cada componente de más en un archivo es una pregunta sobre el otro.
Una SBOM de CRACI generada durante el build
CRACI exporta los mismos formatos. Lo que cambia es de dónde procede el contenido: registra lo que descargó cada job de GitHub Actions, de modo que cada componente de la SBOM se incorporó realmente al build, y los paquetes restaurados desde cachés de CI se marcan como tales. Las GitHub Actions que ejecutó el workflow también aparecen como componentes, fijadas al commit utilizado. La SBOM de cada job incluye además un estado de completitud, de modo que las lagunas se declaran en lugar de dejar que usted las encuentre. Consulte generación de SBOM durante el build o cómo se comparan las herramientas de SBOM.
Ejemplos de SBOM: preguntas frecuentes
¿Qué aspecto tiene una SBOM?
Normalmente es un archivo JSON, a veces XML. Empieza con datos sobre la propia SBOM, como la herramienta y la marca de tiempo; después enumera cada componente con su nombre, versión, identificador y licencia, y por último describe cómo dependen unos componentes de otros.
¿Una SBOM es un archivo JSON?
Normalmente sí, porque JSON es la codificación más utilizada tanto de CycloneDX como de SPDX. Ambos formatos tienen también otras codificaciones, y SPDX cuenta además con una forma de texto tag-value.
¿Qué es una purl en una SBOM?
Una purl, o package URL, es un identificador estándar de un paquete, como pkg:npm/[email protected]. Nombra el ecosistema, el paquete y la versión en una sola cadena, lo que permite a las herramientas cotejar el componente con los datos de vulnerabilidades de forma fiable.
¿Cuántos componentes debería tener una SBOM?
No hay un número correcto, pero debería incluir las dependencias transitivas, que suelen superar con creces a las directas. Muy pocos componentes para una aplicación grande suele significar que la herramienta solo vio una parte.
¿Se puede ver una SBOM de un proyecto de código abierto?
A veces. Algunos proyectos publican SBOM con sus versiones, y GitHub puede exportar una a partir del grafo de dependencias de un repositorio. Esa exportación refleja lo que declara el repositorio, no lo que utilizó un build concreto.
Compare su SBOM con una registrada
Ejecute un workflow de GitHub Actions en CRACI y vea qué componentes no enumera su SBOM actual.
Reservar una demo