Corre después del gate de CRITICAL de Trivy, sobre la imagen ya construida. Genera CycloneDX y SPDX, publicados como artifact sbom-v1.0.X en cada build. Validado contra la imagen real: 3528 componentes CycloneDX / 228 paquetes SPDX. Documenta en docs/devsecops/sbom.md el propósito (trazabilidad tipo "log4shell"), diferencia entre formatos, y un hallazgo real (yarn empaquetado sin usarse, mismo patrón que el npm sacado en el fix de Trivy).
5.0 KiB
SBOM (Syft) — inventario de software
!!! info "Qué es un SBOM"
SBOM = Software Bill of Materials — literalmente, una "lista de
materiales" del software, igual que la lista de ingredientes de un
producto. Es un documento (JSON, en este caso) que enumera cada
paquete que terminó dentro de la imagen final: nombre, versión
exacta, de dónde viene (npm, deb, etc.) y, cuando aplica, su
licencia.
[Syft](https://github.com/anchore/syft) genera ese inventario
inspeccionando la imagen Docker ya construida — no necesita acceso al
código fuente ni a `package.json`, lee directamente lo que quedó
instalado en los layers de la imagen.
Por qué importa: el escenario "log4shell"
En diciembre de 2021 apareció una vulnerabilidad crítica en Log4j (una librería de logging de Java) usada, directa o indirectamente, en una cantidad enorme de software. La pregunta que todo equipo tuvo que responder en horas, no en días, fue: "¿nosotros usamos esto, en algún lugar, aunque sea una dependencia de una dependencia?"
Sin un SBOM, esa respuesta implica revisar manualmente cada
package.json, cada imagen Docker, cada servicio — y confiar en que no
se te escapó una dependencia transitiva de tres niveles de profundidad.
Con un SBOM generado en cada build y guardado como artifact, la respuesta
es una búsqueda de texto sobre un archivo:
grep -i "nombre-del-paquete-afectado" sbom.cdx.json
Si aparece, sabés exactamente en qué versión, y podés cruzarlo contra el aviso de seguridad para saber si tu versión específica está afectada — en minutos, no en una auditoría manual del repo completo.
Qué genera este pipeline
Un step de Syft corre sobre la imagen ya construida (la misma que pasó el gate de CRITICAL de Trivy) y produce dos formatos del mismo inventario, publicados como artifact del pipeline:
sbom.cdx.json— CycloneDX, el formato con mejor soporte en herramientas de consulta/alertas automáticas de CVEs.sbom.spdx.json— SPDX, el estándar ISO, más orientado a cumplimiento de licencias y trazabilidad legal.
No hay una razón fuerte para elegir solo uno en esta etapa — generar ambos cuesta segundos y cada formato es mejor para un caso de uso distinto, así que se publican los dos.
Resultado real de este build
Corriendo Syft contra la imagen real de workloads/ecommerce:
| Formato | Paquetes listados |
|---|---|
| CycloneDX | 3528 componentes |
| SPDX | 228 paquetes |
!!! tip "¿Por qué el número es tan distinto entre formatos?"
No es un error — cada formato tiene un nivel de detalle distinto.
CycloneDX de Syft incluye entradas más granulares (variantes,
sub-paquetes, entradas sin versión resuelta marcadas UNKNOWN)
mientras que SPDX agrupa a un nivel más alto. Para "¿tengo este
paquete, sí o no?" cualquiera de los dos sirve; para conteos exactos,
hay que saber cuál se está mirando.
Ejemplo de una entrada real (sbom.cdx.json, recortado):
{
"name": "next",
"version": "15.5.10",
"licenses": [{ "license": { "id": "MIT" } }],
"purl": "pkg:npm/[email protected]",
"properties": [
{ "name": "syft:package:language", "value": "javascript" },
{ "name": "syft:package:type", "value": "npm" }
]
}
El campo purl (Package URL) es el identificador estándar que usan
Trivy, Syft, GitHub Advisories y la mayoría de las bases de datos de
CVEs para referirse a "este paquete, en este ecosistema, en esta
versión" — es lo que hace posible cruzar un SBOM contra un aviso de
seguridad de forma automática, sin depender de que el nombre coincida
exactamente en texto libre.
!!! example "El SBOM también sirve para encontrar cosas que sobran"
Revisando el inventario real apareció [email protected] — viene
empaquetado en la imagen base de Node igual que el npm que ya se
sacó del stage final en el fix de Trivy. No es una
vulnerabilidad activa hoy, pero es exactamente el tipo de hallazgo
que un SBOM hace visible para revisar después: herramientas que
viajan en la imagen de producción sin que el runtime las necesite.
Cómo se consulta
El SBOM se publica como artifact del pipeline (sbom-v1.0.X, con ambos
archivos) en cada build. Para consultarlo:
- Descargar el artifact de la corrida del pipeline que te interesa
(o del último build de
main, para saber qué corre en producción ahora mismo). - Buscar el paquete en cuestión:
(o
python3 -c " import json d = json.load(open('sbom.cdx.json')) for c in d['components']: if c['name'] == 'next': print(c['name'], c['version']) "grep -A3 '"name": "next"' sbom.cdx.jsonsi no hay Python a mano). - Si el paquete aparece, confirmar la versión contra el aviso de seguridad para saber si aplica.
No hace falta memorizar el formato — el punto de tener el SBOM ya generado es no depender de reconstruir esta información bajo presión el día que aparezca la próxima CVE grande.