123% más CVE notificadas al día en 2026 que el año pasado.

SBOM

Lo que se les escapa a los generadores de SBOM de código abierto

Syft, Trivy y cdxgen son capaces, gratuitos y muy utilizados. Los tres construyen una SBOM a partir de los archivos que usted les indica: lockfiles, manifiestos o paquetes instalados. Por eso discrepan en el mismo repositorio, y por eso ninguno ve lo que el build descargó fuera de esos archivos.

Actualizado el

What a scanner reads versus what the build pulled in A scanner reads the lockfile, which lists direct packages A, B and C and transitive packages D and E, so its SBOM contains only those. CRACI sees the network traffic into the build job, so its recorded SBOM also contains the hidden dependencies no lockfile lists: code downloaded by an install hook, a download by a build script, and the base image layers. A scanner reads the lockfile package-lock.json direct A B C transitive D E Scanned SBOM A, B, C, D, E only what the lockfile lists CRACI sees the traffic into the build A B C D E install hook download build script download base image layers build job on CRACI Recorded SBOM every package it fetched, hidden too Dashed: hidden dependencies, listed in no lockfile

Cómo generar una SBOM con cada herramienta

Cada herramienta necesita un solo comando para un directorio de código fuente o una imagen de contenedor, con salida en CycloneDX o SPDX:

# Syft: a source directory or a container image
syft ./my-project -o cyclonedx-json=sbom.cdx.json
syft my-image:latest -o spdx-json=sbom.spdx.json

# Trivy: a filesystem or a container image
trivy fs --format cyclonedx --output sbom.cdx.json .
trivy image --format spdx-json --output sbom.spdx.json my-image:latest

# cdxgen: the current directory, optionally with a project type
cdxgen -o bom.json .
cdxgen -t js -o bom.json .

Los comandos son la parte fácil. Lo que acaba en el archivo depende de lo que lee cada herramienta, y no leen las mismas cosas.

Qué lee cada herramienta

Herramienta Directorio de código fuente Imagen de contenedor Conviene saber
Syft Un conjunto predeterminado de catalogadores para directorios, que lee las dependencias declaradas Un conjunto predeterminado de catalogadores para imágenes, que lee los paquetes instalados Los catalogadores se eligen según el tipo de escaneo. syft cataloger list muestra cuáles se ejecutan, y --select-catalogers los añade o los quita.
Trivy Lockfiles; para Node.js, package-lock.json, yarn.lock, pnpm-lock.yaml y bun.lock Para Node.js, los archivos package.json bajo node_modules Deja fuera las dependencias de desarrollo, salvo que pase --include-dev-deps.
cdxgen Primero los lockfiles, que incluyen las dependencias de desarrollo; para Node.js, también analiza los imports del código Compatible Defina el tipo de proyecto con -t para limitar lo que busca.

Por qué discrepan en el mismo repositorio

Apunte las tres a un mismo commit y obtendrá tres listas distintas. Ninguna está rota. Cada una sigue sus propias reglas documentadas:

  • Sin lockfile, sin dependencias. Express 5.2.1 no incluye ningún lockfile en el repositorio. En un checkout limpio, una herramienta que resuelve dependencias a partir de lockfiles o paquetes instalados no tiene ni lo uno ni lo otro, de modo que las dependencias npm declaradas en package.json nunca llegan a la SBOM. Aun así, escribe un documento válido con lo demás que haya reconocido.
  • Instalado o declarado. Haber ejecutado o no una instalación antes del escaneo puede importar más que la herramienta que utilice. En una copia instalada del mismo repositorio, un solo ajuste de catalogadores de Syft decide si los paquetes npm instalados aparecen o no.
  • Dependencias de desarrollo. Trivy las deja fuera por defecto y cdxgen las incluye, de modo que el mismo lockfile da dos respuestas a la pregunta de qué hay en este proyecto.
  • Nombres y versiones. Las herramientas identifican algunos componentes con distintos tipos de package URL, o fijan una GitHub Action a un SHA de commit donde otra indica una etiqueta. Una búsqueda de vulnerabilidades basada en el identificador equivocado da una respuesta errónea que parece fiable.
  • Ningún manifiesto. El repositorio anthropics/claude-code no tiene ningún manifiesto de dependencias, y su paquete npm envuelve un binario precompilado. Lo que devuelve cada herramienta dice más de la herramienta que del proyecto.

Lo que se les escapa a todas: las dependencias ocultas

El límite más profundo es común. Un escáner lee el lockfile o la salida del build y deduce a partir de ahí qué entró, a posteriori. Todo lo que el build descargó fuera de esos archivos nunca llega a la SBOM. Estas son las dependencias ocultas:

  • Hooks de instalación. Los scripts preinstall y postinstall de npm se ejecutan durante la instalación y pueden descargar más código. Así actuó el gusano Shai-Hulud.
  • Scripts de build, como los scripts de build de Rust que descargan lo que necesitan durante el build.
  • Imágenes base y sus capas del sistema operativo en un build de contenedor, que ningún lockfile de lenguaje enumera.
  • Paquetes restaurados desde cachés de CI, que pueden no coincidir con el lockfile actual. Consulte lo que oculta la caché de GitHub Actions.
  • Herramientas de build instaladas en pasos de configuración, con sus propios árboles de dependencias.
  • Versiones transitivas resueltas durante el build cuando el lockfile falta, está desactualizado o no se utiliza en una instalación congelada. Consulte dependencias transitivas.

Escanear la salida después no cierra esa laguna. Un binario terminado, sobre todo el código compilado como Rust, deja al escáner adivinando qué entró en él. Los escáneres de SCA comerciales trabajan con los mismos tipos de archivos y comparten los mismos puntos ciegos. CRACI ha encontrado paquetes vulnerables de los que Snyk y Aikido no informaron, porque los componentes nunca estuvieron en lo que escanearon.

How a scanned SBOM and a recorded SBOM are made Left, a scanner: it reads the lockfile after the build, which lists packages A to E, so its SBOM contains A to E. The build also fetched code through an install hook, a build script download and a base image, which are in no lockfile, so the scanned SBOM is missing them. Right, CRACI: it sees the traffic coming into the build, so all eight packages, including the three hidden dependencies, land in the recorded SBOM. Scanner reads files after the build package-lock.json A B C D E the build also fetched install hook download build script download base image layers in no lockfile, so the scan never sees them Scanned SBOM A B C D E missing missing missing CRACI sees the traffic into the build the network build job on CRACI every package that comes in Recorded SBOM A B C D E install hook build script base image hidden ones too
A scanner can only list what the lockfile or the output declares. CRACI sees what actually came into the build, including the hidden dependencies.

Las herramientas también forman parte de su cadena de suministro

Un escáner se ejecuta en su CI con acceso a su código y, a menudo, a sus secretos. En marzo de 2026, el aviso de Aqua Security (CVE-2026-33634) describió una versión maliciosa v0.69.4 de Trivy y etiquetas envenenadas de trivy-action y setup-trivy que robaban credenciales de los runners de CI. Fije las acciones de escáneres a SHA de commit completos y consulte el aviso para comprobar las versiones que ejecuta.

Cómo comprobar su propia SBOM

  1. Ejecute dos generadores sobre el mismo commit y compare las package URL que indican.
  2. Compruebe si el repositorio incluye un lockfile y si CI instala a partir de él con una instalación congelada.
  3. Escanee después del paso de instalación además de antes, y compare.
  4. Compare la lista con lo que su registro de build muestra como descargado, incluidos los pasos de configuración y las restauraciones de caché.

Si las listas difieren, la SBOM que publica depende de la herramienta que haya ejecutado por casualidad, no de lo que distribuyó.

Registre el build en su lugar

CRACI ve el tráfico; los escáneres no. Es un runner de GitHub Actions que ve el tráfico de red que entra en cada build, de modo que su SBOM registra cada paquete que incorporó el job, a cualquier profundidad del árbol, incluidas las dependencias ocultas y los paquetes restaurados desde cachés de CI. No hay ningún directorio al que apuntar ni ningún catalogador que elegir. Cuando un registro no pudo verlo todo, por ejemplo porque un job permitió tráfico no monitorizado, la SBOM lo indica con su estado de completitud.

Registrar también importa porque los builds rara vez son reproducibles. Compile el mismo commit dos veces seguidas y el gestor de paquetes puede resolver e instalar en otro orden, de modo que el segundo build puede contener paquetes distintos. Solo la SBOM registrada durante el build que produjo una versión demuestra lo que contiene esa versión.

Conserve Syft o Trivy para las imágenes y binarios de terceros que usted no haya compilado. Para sus propias versiones, consulte SBOM durante el build o reserve una demo para comparar una SBOM registrada con la de su herramienta actual en uno de sus repositorios.

Generadores de SBOM de código abierto: preguntas frecuentes

¿Qué es mejor para las SBOM, Syft o Trivy?

Están hechos para trabajos distintos. Syft es un generador de SBOM dedicado, con muchos catalogadores y atestaciones firmadas; Trivy es un escáner de seguridad que escribe SBOM como una de sus salidas. Ambos leen los archivos que tienen delante, de modo que, en un mismo repositorio, la mayor diferencia suele ser si hay un lockfile en el repositorio y si las dependencias se instalaron antes del escaneo.

¿Por qué mi SBOM no muestra ninguna dependencia?

Lo más habitual es que el repositorio no incluya ningún lockfile y que no se haya instalado nada antes del escaneo. Un generador que lee lockfiles o paquetes instalados no tiene entonces nada que leer, y aun así escribe una SBOM válida. Incluya el lockfile en el repositorio o escanee después del paso de instalación.

¿Trivy incluye las dependencias de desarrollo en la SBOM?

No por defecto. La documentación de Trivy para Node.js indica que no notifica las dependencias de desarrollo, salvo que pase --include-dev-deps. cdxgen, en cambio, analiza los lockfiles e incluye las dependencias de desarrollo. Dos herramientas pueden discrepar sobre el mismo proyecto solo por este motivo.

¿Puedo fiarme de una SBOM de un generador de código abierto?

Para lo que leyó, sí. La cuestión es lo que no leyó: cachés, herramientas de build, descargas, scripts de instalación y binarios sin metadatos de paquetes. Trate una SBOM escaneada como una descripción de los archivos a los que apuntó la herramienta, no del build que creó su versión.

¿Cuál es la mejor herramienta de SBOM?

Para el software que compila usted mismo, la SBOM más completa se obtiene registrando el build en lugar de escanear archivos. CRACI registra cada paquete que descarga cada job de GitHub Actions, también desde cachés, y ha encontrado paquetes vulnerables de los que Snyk y Aikido no informaron. Para las imágenes y binarios de terceros que usted no haya compilado, un escáner como Syft o Trivy sigue siendo la opción práctica.

Ponga una SBOM registrada junto a la de su escáner

Ejecute un workflow de GitHub Actions en CRACI y compare su SBOM de paquetes descargados con lo que indicaron Syft, Trivy o cdxgen.

Reservar una demo