Skip to main content

Cómo generar un SBOM para aplicaciones JavaScript y Node.js

Escrito por
Blog Header Vuln card blog

22 de mayo de 2023

0 minutos de lectura

Nota del editor: 31 de mayo de 2023

Ahora que el comando sbom de Snyk está disponible de forma general, actualizamos esta publicación para mostrar cómo usar Snyk para generar un SBOM según la especificación SPDX.

¿Qué es una SBOM?

SBOM es la sigla de lista de materiales de software, que es una lista de todos los paquetes npm de código abierto que forman parte de tu proyecto. Sin embargo, no se limita al código abierto ni a los paquetes de software: también puede incluir bibliotecas del sistema operativo, un inventario de microservicios y mucho más.

Los paquetes de software de npm se representan en dos archivos: package.json, que contiene tus dependencias directas, y un archivo de bloqueo, como package-lock.json o yarn.lock, que representa todo el árbol de dependencias instaladas al compilar tus proyectos de aplicaciones JavaScript o Node.js.

¿Por qué es importante mantener un SBOM para una aplicación de Node.js?

El ecosistema de JavaScript no es ajeno a los incidentes de seguridad que afectan a los desarrolladores. Algunos ejemplos recientes son el protestware, un tipo de malware malicioso que buscaba corromper los datos del disco, y los paquetes npm maliciosos que aprovechan ataques de confusión de dependencias para infiltrarse en los sistemas informáticos de organizaciones internas.

Con la adopción generalizada de las bibliotecas de código abierto y el aumento de los incidentes de seguridad en repositorios de software como npm, es esencial poder evaluar e identificar si una versión específica de una dependencia se usa en tu aplicación. Además, estos riesgos de seguridad hacen aún más necesario actuar con rapidez, ya sea actualizando dependencias de forma continua o buscando y reemplazando componentes en poco tiempo.

«Un registro formal que contiene los detalles y las relaciones de la cadena de suministro de los distintos componentes utilizados para crear software» — NIST (Instituto Nacional de Estándares y Tecnología)

Como desarrollador, un SBOM te ofrece un inventario integral de las dependencias que componen tu stack tecnológico. Esto te permite actualizar las dependencias obsoletas y vulnerables, o reemplazar paquetes que no tienen una solución disponible o usan una licencia incompatible. Además, puedes descartar vulnerabilidades como no aplicables según tus casos de uso específicos. Por último, es posible que los equipos de seguridad y operaciones te pidan generar un SBOM para tus aplicaciones JavaScript y Node.js, debido a los requisitos gubernamentales de cumplimiento en ciberseguridad que exigen llevar un control de la seguridad de la cadena de suministro.

Usa la API de Snyk para generar un SBOM para una aplicación Node.js

Snyk es una plataforma gratuita de seguridad para desarrolladores que automatiza la detección y corrección de problemas de seguridad. Al monitorear tus proyectos con Snyk, te aseguras de recibir las correcciones de seguridad a tiempo.

Actualmente, las funciones de SBOM solo están disponibles en los planes de pago. Si tienes uno, comencemos a generar un SBOM para una aplicación Node.js.

Requisitos previos:

  • Una cuenta de pago de Snyk.

  • Acceso a la API de Snyk

  • Un proyecto de JavaScript o Node.js importado a la plataforma de Snyk

  • La herramienta de línea de comandos curl

Paso 1: Importa un proyecto de JavaScript a Snyk

El primer paso es importar un proyecto a la plataforma de Snyk para que se puedan analizar, monitorear y revisar todas las dependencias y bibliotecas de npm que contiene.

Haz clic aquí para ver el proceso paso a paso para importar un proyecto (o un video rápido de 1 minuto, si lo prefieres).

Paso 2: Prepara tu token de Snyk

Para hacer una llamada a la API de la plataforma de Snyk, necesitaremos un token de la API de Snyk con permisos para consultar el endpoint de informes SBOM del proyecto.

Si usas la CLI de Snyk, una forma de encontrar el token de la API de Snyk es ejecutar el siguiente comando:

$ snyk config get api

Sin embargo, es posible que este token de la API de Snyk no tenga los privilegios necesarios para realizar solicitudes a la organización o al proyecto. En su lugar, te recomendamos generar una nueva cuenta de servicio dedicada a esta tarea, para que puedas automatizarla desde CI y otros sistemas.

Para crear una cuenta de servicio, ve a la sección settings de tu organización y luego a service accounts. Asigna un nombre a la nueva cuenta de servicio y elige el rol Org Admin. Después, haz clic en el botón Create.

Configuración de cuentas de servicio de Snyk que muestra una nueva cuenta llamada “service_account_for_sbom_report”, con el rol de administrador de la organización y el botón Crear.

Se te mostrará un token de la API. Guárdalo en un lugar seguro y tenlo a mano: pronto lo usaremos para consultar la API de Snyk y generar un SBOM.

Encontrarás más información en la documentación de usuario de Snyk sobre la administración de cuentas de servicio.

Paso 3: Encuentra los ID de la organización y del proyecto

En la misma página de configuración encontrarás el ID de tu organización. Cópialo y tenlo a mano:

Página de configuración de la organización de Snyk que muestra la pestaña General y el campo ID de la organización con un botón Copiar

A continuación, obtendremos el ID del proyecto de JavaScript que importamos a Snyk.

Ve a Projects, busca el proyecto para el que quieres generar un SBOM y haz clic para ver sus detalles:

Panel de seguridad con proyectos de análisis de Dockerfile, package.json y código, y cantidades de proyectos importados, evaluados y con problemas.

En la página de detalles del proyecto, haz clic en la pestaña Settings, en la esquina superior derecha, y desplázate hacia abajo para copiar el ID del proyecto:

Página de configuración del proyecto de Snyk que muestra la pestaña General, la frecuencia de pruebas diaria y el campo ID del proyecto.

Paso 4: Genera el SBOM con curl y la API de Snyk

A estas alturas, deberías tener lo siguiente:

  • Un token de la API de Snyk

  • El ID de la organización

  • El ID del proyecto

Ya podemos enviar una solicitud a la API y obtener el informe SBOM. Usaremos la herramienta de línea de comandos curl para enviar la solicitud HTTP a la API de Snyk:

curl -H "Authorization: token $SNYK_TOKEN" \
"https://api.snyk.io/rest/orgs/<ORG_ID>/projects/<PROJECT_ID>/sbom?version=2023-03-20&format=cyclonedx1.4%2Bjson"

Los resultados que devuelve la API están en formato JSON y usan el estándar CycloneDX para el informe SBOM. Ten en cuenta la codificación de URL %2B al final del parámetro de consulta de la API, que codifica el carácter +.

Consejo: Puedes especificar varias instancias del parámetro de consulta format para recibir el SBOM en varios formatos.

Es posible que los datos de salida sean demasiado extensos o no tengan el formato adecuado para mostrarse en la consola. Podemos agregar una tubería a jq para que sean más claros y fáciles de leer:

curl -H "Authorization: token $SNYK_TOKEN" \
"https://api.snyk.io/rest/orgs/<ORG_ID>/projects/<PROJECT_ID>/sbom?version=2023-03-20&format=cyclonedx+json" | jq .

El informe SBOM generado ahora es legible y, si importaste un proyecto administrado con el gestor de paquetes npm de JavaScript, debería verse más o menos así:

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "version": 1,
  "metadata": {
    "timestamp": "2023-02-21T11:01:07Z",
    "tools": [
      {
        "vendor": "Snyk",
        "name": "Snyk Open Source"
      }
    ],
    "component": {
      "bom-ref": "1-goof@1.0.1",
      "type": "application",
      "name": "goof",
      "version": "1.0.1",
      "purl": "pkg:npm/goof@1.0.1"
    },
    "properties": [
      {
        "name": "snyk:org_id",
        "value": "<REDACTED>"
      },
      {
        "name": "snyk:project_id",
        "value": "<REDACTED>"
      }
    ]
  },
  "components": [
    {
      "bom-ref": "2-adm-zip@0.4.7",
      "type": "library",
      "name": "adm-zip",
      "version": "0.4.7",
      "purl": "pkg:npm/adm-zip@0.4.7"
    },
    {
      "bom-ref": "3-bytes@1.0.0",
      "type": "library",
      "name": "bytes",
      "version": "1.0.0",
      "purl": "pkg:npm/bytes@1.0.0"
    },

El informe SBOM generado es un documento CycloneDX 1.4 válido que contiene la lista de materiales de software del proyecto de Snyk indicado.

Incluye metadatos detallados y también informa sobre las dependencias transitivas para destacar las bibliotecas de las que dependen otros componentes. Por ejemplo, en el mismo informe anterior:

  {
      "ref": "63-utils-merge@1.0.0"
    },
    {
      "ref": "64-serve-static@1.9.3",
      "dependsOn": [
        "34-escape-html@1.0.1",
        "53-parseurl@1.3.3",
        "62-send@0.12.3",
        "63-utils-merge@1.0.0"
      ]
    },
    {
      "ref": "65-type-is@1.6.16",
      "dependsOn": [
        "6-media-typer@0.3.0",
        "37-mime-types@2.1.23"
      ]
    },

En esta etapa, el formato de salida CycloneDX incluye la siguiente información:

  • Dependencias directas

  • Dependencias transitivas y sus relaciones con los paquetes de los que dependen.

  • Los identificadores de Org y Project de Snyk para los que se generó este SBOM.

  • El nombre de la aplicación o del proyecto para el que se generó este SBOM, si está disponible en el archivo de manifiesto del paquete proporcionado como entrada.

En la documentación de la API puedes explorar más opciones de uso de la API de Snyk para SBOM, como la compatibilidad con la serialización en XML en lugar de JSON o la generación de documentos conforme a la especificación SPDX como estándar de lista de materiales de software.

Ahora puedes automatizar la generación de SBOM para tus dependencias de código abierto. ¿Qué vas a crear a continuación? Cuéntanos en la comunidad de Discord de DevSecOps.

Usa la CLI de Snyk para generar un SBOM para una aplicación Node.js

Si no tienes acceso directo a la API de Snyk, puedes aprovechar la CLI de Snyk. Es compatible con numerosos sistemas operativos y permite buscar, corregir, monitorear y generar informes en todos los productos de Snyk, desde el análisis estático de código hasta la infraestructura como código.

Comencemos a generar un SBOM para cualquier aplicación JavaScript administrada con un gestor de paquetes.

Requisitos previos:

En un directorio de un proyecto JavaScript que ya tenga un archivo de manifiesto package.json, podemos analizar todos los componentes de la lista de materiales de software que contiene.

Tomemos como ejemplo un proyecto Node.js que tiene debug como devDependency y fastify como framework de la aplicación web, entre las dependencias de producción:

{
  "name": "my-sbom-learning-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "debug": "^4.3.4"
  },
  "dependencies": {
    "fastify": "^4.13.0"
  }
}

Con solo dos dependencias directas, ¿cuál es el costo de las dependencias transitivas? Aquí es donde generar un SBOM para el proyecto resulta útil, ya que ofrece una vista completa de sus dependencias. Ejecutemos el siguiente comando snyk, que buscará en el directorio actual un archivo package.json compatible y lo analizará:

snyk sbom --format=cyclonedx1.4+json

{
  "bomFormat": "CycloneDX",
  "specVersion": "1.4",
  "version": 1,
  "metadata": {
    "timestamp": "2023-02-27T08:06:35Z",
    "tools": [
      {
        "vendor": "Snyk",
        "name": "Snyk Open Source"
      }
    ],
    "component": {
      "bom-ref": "1-a@1.0.0",
      "type": "application",
      "name": "a",
      "version": "1.0.0",
      "purl": "pkg:npm/a@1.0.0"
    }
  },
  "components": [
    {
      "bom-ref": "2-fast-deep-equal@3.1.3",
      "type": "library",
      "name": "fast-deep-equal",
      "version": "3.1.3",
      "purl": "pkg:npm/fast-deep-equal@3.1.3"
    },
    {
      "bom-ref": "3-json-schema-traverse@1.0.0",
      "type": "library",
      "name": "json-schema-traverse",
      "version": "1.0.0",
      "purl": "pkg:npm/json-schema-traverse@1.0.0"
    },

El resultado de CycloneDX anterior se recortó a unas 40 líneas para evitar saturar este artículo. La lista completa de materiales de software para una huella tan pequeña de dependencias directas tiene 749 líneas de JSON con formato.

Podemos usar jq para contar cuántas dependencias de código abierto tiene este proyecto:

snyk sbom --format=cyclonedx1.4+json | jq ".components | length"

El resultado es un total de 60 paquetes de código abierto en la lista de materiales de software de este proyecto.

Ahora queda clara la importancia de un SBOM: sirve para mucho más que cumplir los requisitos normativos o de cumplimiento que establece tu equipo de seguridad o una orden gubernamental. Ya sabemos que tu proyecto depende de 60 paquetes de código abierto, no solo de los 2 que instalaste directamente. Este es un aspecto clave de la cadena de suministro de software, cuyas implicaciones de seguridad son importantes y representan riesgos directos para los consumidores.

Al descubrir que tu proyecto depende de 60 paquetes de código abierto, quizá te hagas alguna de estas preguntas:

  1. ¿Alguno de estos paquetes tiene una licencia incompatible con las pautas y el uso de mi organización?

  2. ¿Se mantienen activamente todos estos paquetes?

  3. ¿Qué pasa si se descubre una nueva vulnerabilidad en alguno de estos 60 paquetes?

Estos son algunos de los aspectos relacionados con el estado de los proyectos que buscamos resolver con la ayuda de Snyk Advisor, que proporciona una puntuación basada en la popularidad, el mantenimiento, la seguridad y las métricas de comunidad del proyecto.

Página de Snyk Advisor para el paquete de JavaScript datejs, que muestra su puntuación de salud de 53/100 y detalles sobre el estado del paquete.

Volvamos a los SBOM. A continuación se muestra el uso completo del comando de línea de comandos disponible para analizar proyectos:

$ snyk sbom --file=<file> --format=cyclonedx1.4+json [targetDirectory] 

Genera un SBOM conforme a la especificación SPDX

La CLI de Snyk y los endpoints de la API también son compatibles con la especificación SPDX. Si cambiamos la opción de línea de comandos format a spdx2.3+json, podemos generar un SBOM conforme a SPDX en formato JSON. Así se hace:

$ snyk sbom --format=spdx2.3+json

El resultado será una respuesta JSON parcial como la siguiente, basada en nuestro proyecto de referencia Fastify de antes:

{
  "spdxVersion": "SPDX-2.3",
  "dataLicense": "CC0-1.0",
  "SPDXID": "SPDXRef-DOCUMENT",
  "name": "my-sbom-learning-project@1.0.0",
  "documentNamespace": "https://snyk.io/spdx/sbom-",
  "creationInfo": {
    "licenseListVersion": "3.19",
    "creators": [
      "Tool: Snyk Open Source",
      "Organization: Snyk"
    ],
    "created": "2023-05-30T12:09:22Z"
  },
  "packages": [
    {
      "name": "my-sbom-learning-project",
      "SPDXID": "SPDXRef-1-my-sbom-learning-project-1.0.0",
      "versionInfo": "1.0.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/my-sbom-learning-project@1.0.0"
        }
      ]
    },
    {
      "name": "fastify",
      "SPDXID": "SPDXRef-2-fastify-4.17.0",
      "versionInfo": "4.17.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/fastify@4.17.0"
        }
      ]
    },
    {
      "name": "@fastify/ajv-compiler",
      "SPDXID": "SPDXRef-3-fastify-ajv-compiler-3.5.0",
      "versionInfo": "3.5.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/%40fastify/ajv-compiler@3.5.0"
        }
      ]
    },
    {
      "name": "ajv",
      "SPDXID": "SPDXRef-4-ajv-8.12.0",
      "versionInfo": "8.12.0",
      "downloadLocation": "NOASSERTION",
      "copyrightText": "NOASSERTION",
      "externalRefs": [
        {
          "referenceCategory": "PACKAGE-MANAGER",
          "referenceType": "purl",
          "referenceLocator": "pkg:npm/ajv@8.12.0"
        }
      ]
    },

¿Qué más puedes esperar de un SBOM?

Snyk se compromete a ayudar a los desarrolladores a crear y lanzar aplicaciones seguras, detectando código inseguro al instante en el IDE o mediante solicitudes pull request de corrección automatizadas para repositorios de software en GitHub o Bitbucket.

En este artículo nos centramos en las dependencias de las aplicaciones JavaScript que forman parte del inventario de un SBOM. Sin embargo, este también revela otros datos útiles sobre los componentes de software que se usan en un proyecto. Esta información ampliada puede ser fundamental para comprender no solo la composición de un producto de software, sino también para administrar sus riesgos de seguridad, requisitos de cumplimiento y licencias. Algunos ejemplos de los datos que puede incluir un SBOM son:

  1. Detalles de los componentes: Incluyen información sobre cada componente del software, como el nombre del paquete npm, su versión y su origen (ya sea el repositorio npmjs o uno de GitHub).

  2. Información de licencias: Incluye detalles sobre las licencias que rigen cada componente del software, como su tipo, términos y obligaciones. Quizá estés acostumbrado a los paquetes npm con licencias MIT o Apache, pero una dependencia anidada podría usar una licencia incompatible, como GNU GPL, y exponerte a riesgos legales.

  3. Datos de vulnerabilidades: Incluyen información sobre las vulnerabilidades de seguridad conocidas públicamente que estén asociadas con los paquetes npm utilizados en el software, ya sea que lo afecten de forma directa o indirecta.

  4. Datos criptográficos: Incluyen información sobre los componentes criptográficos que usa el software, como sus algoritmos y tamaños de clave. Por ejemplo, si una aplicación usa un algoritmo inseguro, como el hash MD5, es importante que lo sepas y tomes las medidas necesarias.

  5. Información de compilación: Incluye detalles sobre cómo se compiló el software, como el entorno de compilación, las herramientas utilizadas y los ajustes de configuración.

  6. Metadatos: Incluyen información adicional relevante sobre el software, como el nombre del proyecto, su versión y su autor.

Para ver un ejemplo práctico de cómo puede serte útil un SBOM como desarrollador de JavaScript, considera la siguiente tabla:

Nombre del componente

Versión

Tipo de licencia

Datos de vulnerabilidades

Datos criptográficos

Express

4.4.0

MIT

N/A

Lodash

4.17.16

MIT

N/A

Vue

2.5.16

MIT

N/A

Axios

0.21.0

MIT

N/A

Al momento de escribir este artículo, Snyk expone las dependencias y sus relaciones en los siguientes formatos:

  • CycloneDX versión 1.4 en JSON

  • CycloneDX versión 1.4 en XML

  • SPDX versión 2.3 en JSON

El equipo trabaja para admitir otras secciones de las especificaciones, como vulnerabilidades, licencias y más.

Snyk también te permite trabajar con SBOM de otras maneras:

  • La herramienta de verificación de SBOM es un sitio web gratuito donde puedes cargar un artefacto SBOM para que Snyk encuentre vulnerabilidades en los paquetes npm.

  • Sección sobre SBOM de la API de Snyk

  • La CLI de Snyk

  • Profundiza en la documentación de usuario de SBOM

  • El proyecto de código abierto Bomber puede leer archivos en formato de especificación SBOM como entrada y generar una lista de vulnerabilidades. Puede ser útil si necesitas trabajar con componentes de código cerrado de proveedores. Además, admite a Snyk como proveedor de datos de vulnerabilidades.

Si eres desarrollador de Java o tu organización tiene aplicaciones desarrolladas con Java, consulta el artículo de mi colega Brian Vermeer sobre cómo crear SBOM en Java con Maven y Gradle.

Para una introducción más detallada, te recomiendo leer el artículo de Snyk sobre la lista de materiales de software (SBOM) para la seguridad de la cadena de suministro de código abierto.

Protege tus dependencias de código abierto

Las herramientas de Snyk, diseñadas para desarrolladores, generan pull requests de corrección con un clic para dependencias vulnerables de código abierto y sus dependencias transitivas.

Leer más

blog feature snyk container custom base recommendations
Blog

Presentamos Evo Agentic AppSec: seguridad al ritmo del desarrollo con IA

El desarrollo impulsado por IA supera el ritmo de los flujos de trabajo de seguridad tradicionales. Agentic AppSec de Snyk usa agentes de seguridad para encontrar, corregir y verificar vulnerabilidades de forma continua, mientras las personas definen el estándar.

blog feature ai violet
Blog

VulnBump: ¿Pueden los agentes de IA corregir dependencias vulnerables sin romper la compilación?

VulnBump prueba agentes de IA en 307 actualizaciones reales de dependencias. Una corrección cuenta solo si elimina la vulnerabilidad y mantiene en verde la compilación y las pruebas.

Blog

Los modelos de frontera encontraron las vulnerabilidades. Solo el atacante encontró las cadenas.

El análisis estático encontró las fallas, pero solo las pruebas de ataque en vivo demostraron cómo podían encadenarse para provocar brechas. Una comparación de Evo COS, Claude Security y Claude Code Security.