# 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:

```bash
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](https://cyclonedx.org/), el formato con
  mejor soporte en herramientas de consulta/alertas automáticas de CVEs.
- `sbom.spdx.json` — [SPDX](https://spdx.dev/), 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):

```json
{
  "name": "next",
  "version": "15.5.10",
  "licenses": [{ "license": { "id": "MIT" } }],
  "purl": "pkg:npm/next@15.5.10",
  "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ó `yarn@1.22.22` — viene
    empaquetado en la imagen base de Node igual que el `npm` que ya se
    sacó del stage final en el fix de [Trivy](trivy.md). 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:

1. 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).
2. Buscar el paquete en cuestión:
   ```bash
   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'])
   "
   ```
   (o `grep -A3 '"name": "next"' sbom.cdx.json` si no hay Python a mano).
3. 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.
