Skip to main content

Comment générer un SBOM pour les applications JavaScript et Node.js

Écrit par
Blog Header Vuln card blog

22 mai 2023

0 minutes de lecture

Note de la rédaction : 31 mai 2023

Maintenant que la commande sbom de Snyk est généralement disponible, cet article a été mis à jour pour montrer comment utiliser Snyk afin de générer un SBOM conforme à la spécification SPDX.

Qu’est-ce qu’une SBOM ?

SBOM est l’acronyme de Software Bill of Materials, c’est-à-dire une liste de tous les packages npm open source qui font partie de votre projet. Mais une SBOM ne se limite pas aux logiciels ou aux packages open source : elle peut également inclure les bibliothèques du système d’exploitation, l’inventaire des microservices et bien plus encore.

Les packages npm de votre logiciel sont répartis dans deux fichiers : package.json, qui contient vos dépendances directes, et un fichier de verrouillage tel que package-lock.json ou yarn.lock, qui représente l’ensemble de l’arborescence des dépendances installées lors de la compilation de vos projets JavaScript ou Node.js.

Pourquoi est-il important de tenir à jour un SBOM pour une application Node.js ?

L’écosystème JavaScript n’est pas à l’abri des incidents de sécurité qui touchent les développeurs. Parmi les exemples récents, citons le protestware, un type de logiciel malveillant visant à corrompre les données des disques, ainsi que des packages npm malveillants exploitant des attaques par confusion de dépendances pour infiltrer les systèmes informatiques d’organisations internes.

Avec l’adoption généralisée des bibliothèques open source et la multiplication des incidents de sécurité sur des dépôts logiciels comme npm, il est essentiel de pouvoir évaluer et déterminer précisément si une version donnée d’une dépendance est utilisée dans votre application. De plus, ces risques de sécurité renforcent la nécessité d’agir rapidement en mettant à niveau les dépendances ou en les remplaçant en peu de temps.

« Un registre formel contenant les détails et les relations de la chaîne d’approvisionnement des différents composants utilisés pour créer un logiciel » — NIST (National Institute of Standards and Technology)

En tant que développeur, un SBOM vous offre un inventaire complet des dépendances qui composent votre pile technologique. Vous pouvez ainsi mettre à jour les dépendances obsolètes et vulnérables, ou remplacer les packages qui ne peuvent pas être corrigés ou dont la licence est incompatible. Il vous permet également de considérer certaines vulnérabilités comme non applicables en fonction de vos cas d’usage spécifiques. Enfin, vos équipes Sécurité et Opérations vous demanderont probablement de générer un SBOM pour vos applications JavaScript et Node.js, afin de répondre aux exigences gouvernementales en matière de cybersécurité et de suivre la sécurité de la chaîne d’approvisionnement.

Générer un SBOM pour une application Node.js à l’aide de l’API Snyk

Snyk est une plateforme gratuite de sécurité pour les développeurs qui automatise la détection et la correction des problèmes de sécurité. En surveillant vos projets avec Snyk, vous bénéficiez de correctifs de sécurité en temps voulu.

Pour le moment, les fonctionnalités SBOM sont uniquement disponibles avec les offres payantes. Si vous disposez de l’une de ces offres, commençons à générer un SBOM pour une application Node.js. 

Prérequis :

  • Un compte Snyk payant.

  • Un accès à l’API Snyk

  • Un projet JavaScript ou Node.js importé sur la plateforme Snyk

  • L’outil en ligne de commande curl

Étape 1 : importer un projet JavaScript dans Snyk

Commencez par importer un projet sur la plateforme Snyk afin que toutes ses dépendances et bibliothèques npm puissent être analysées, surveillées et examinées.

Cliquez ici pour suivre la procédure d’importation d’un projet, étape par étape (ou regarder une courte vidéo d’une minute, si vous préférez).

Étape 2 : préparer votre jeton Snyk

Pour envoyer un appel API à la plateforme Snyk, nous avons besoin d’un jeton d’API Snyk autorisé à interroger le point de terminaison de génération de rapports SBOM du projet.

Si vous utilisez la CLI Snyk, vous pouvez trouver le jeton d’API Snyk en exécutant la commande suivante :

$ snyk config get api

Toutefois, ce jeton d’API Snyk n’a peut-être pas les privilèges nécessaires pour envoyer des requêtes à l’organisation ou au projet. Nous vous conseillons plutôt de créer un compte de service dédié à cette tâche, afin de pouvoir l’automatiser depuis la CI et d’autres systèmes.

Pour créer un compte de service, accédez aux paramètres de votre organisation, puis à comptes de service. Saisissez un nom pour le nouveau compte de service, attribuez-lui le rôle Org Admin, puis cliquez sur le bouton Créer.

Paramètres des comptes de service Snyk affichant un nouveau compte nommé « service_account_for_sbom_report », avec le rôle d’administrateur d’organisation et le bouton Créer.

Un jeton d’API vous sera présenté. Enregistrez-le dans un endroit sûr et gardez-le à portée de main : nous l’utiliserons bientôt pour interroger l’API Snyk et générer un SBOM.

Pour en savoir plus, consultez la documentation utilisateur Snyk sur la gestion des comptes de service.

Étape 3 : trouver les identifiants de l’organisation et du projet

Vous trouverez l’identifiant de votre organisation dans la même page de paramètres. Copiez-le et gardez-le à portée de main :

Page des paramètres d’organisation Snyk affichant l’onglet Général et le champ ID de l’organisation avec un bouton Copier

Nous allons ensuite récupérer l’identifiant du projet JavaScript que nous avons importé dans Snyk.

Accédez à Projets, recherchez le projet pour lequel vous souhaitez générer un SBOM, puis cliquez dessus pour afficher ses détails :

Tableau de bord de sécurité listant les projets Dockerfile, package.json et d’analyse de code, avec le nombre d’éléments importés, testés et de problèmes détectés.

Dans la page des détails du projet, cliquez sur l’onglet Paramètres en haut à droite, puis faites défiler la page pour copier l’identifiant du projet :

Page Paramètres du projet Snyk affichant l’onglet Général, la fréquence de test quotidienne et le champ ID du projet.

Étape 4 : générer le SBOM avec curl et l’API Snyk 

Vous devriez maintenant disposer des éléments suivants :

  • Un jeton d’API Snyk

  • L’identifiant de l’organisation

  • L’identifiant du projet

Nous sommes prêts à envoyer une requête API et à obtenir le rapport SBOM. Nous utiliserons l’outil en ligne de commande curl pour envoyer une requête HTTP à l’API 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"

Les résultats renvoyés par l’API sont au format JSON et utilisent la norme CycloneDX pour le rapport SBOM. Notez l’encodage URL %2B à la fin du paramètre de requête API, qui encode le caractère +.

Conseil : vous pouvez spécifier plusieurs valeurs pour le paramètre de requête format afin de recevoir plusieurs versions du SBOM.

Les données générées peuvent être trop volumineuses ou mal formatées pour s’afficher dans la console. Nous pouvons donc ajouter un pipe vers jq pour les rendre plus lisibles :

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 .

Le rapport SBOM généré est maintenant lisible. Si vous avez importé un projet géré par le gestionnaire de packages npm de JavaScript, il devrait ressembler à ceci :

{
  "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"
    },

Le rapport SBOM généré est un document CycloneDX 1.4 valide qui répertorie les composants logiciels du projet Snyk concerné.

Il contient des métadonnées détaillées et indique également les dépendances transitives afin de mettre en évidence les bibliothèques dont dépendent d’autres composants. Par exemple, dans le rapport ci-dessus :

  {
      "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"
      ]
    },

À ce stade, le format de sortie CycloneDX fournit les informations suivantes :

  • Dépendances directes

  • Dépendances transitives et relations avec les packages dont elles dépendent.

  • Les identifiants Org et Project Snyk pour lesquels ce SBOM a été généré.

  • Le nom de l’application ou du projet pour lequel ce SBOM a été généré, s’il est disponible dans le fichier manifeste du package fourni en entrée.

Consultez la documentation de l’API pour découvrir d’autres possibilités d’utilisation de l’API Snyk pour les SBOM, notamment la sérialisation au format XML plutôt qu’en JSON, ou la génération d’un document conforme à la spécification SPDX comme norme de nomenclature logicielle. 

Vous pouvez désormais automatiser la génération de SBOM pour vos dépendances open source. Que souhaitez-vous créer ensuite ? Faites-le-nous savoir dans la communauté Discord DevSecOps.

Générer un SBOM pour une application Node.js avec la CLI Snyk

Si vous n’avez pas directement accès à l’API Snyk, vous pouvez utiliser la CLI Snyk. Compatible avec de nombreux systèmes d’exploitation, elle permet de détecter, corriger, surveiller et générer des rapports pour tous les produits Snyk, de l’analyse statique du code à l’infrastructure as code.

Commençons par générer un SBOM pour toute application JavaScript gérée par un gestionnaire de packages.

Prérequis :

Dans le répertoire d’un projet JavaScript qui contient déjà un fichier manifeste package.json, nous pouvons analyser tous les composants répertoriés dans sa nomenclature logicielle.

Prenons un projet Node.js avec debug comme dépendance de développement et fastify comme framework d’application web parmi les dépendances de production :

{
  "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"
  }
}

Quelle est donc l’étendue des dépendances transitives pour seulement deux dépendances directes ? C’est là que la génération d’un SBOM révèle toute sa valeur, en offrant une vue complète des dépendances du projet. Exécutons la commande snyk suivante : elle recherchera dans le répertoire courant un fichier package.json compatible et l’analysera :

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"
    },

La sortie CycloneDX ci-dessus est limitée à une quarantaine de lignes pour éviter d’encombrer cet article. La nomenclature logicielle complète de ce projet, qui ne compte qu’un petit nombre de dépendances directes, représente 749 lignes de JSON formaté.

Nous pouvons utiliser jq pour compter le nombre de dépendances open source de ce projet :

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

Nous obtenons ainsi un total de 60 packages open source dans la nomenclature logicielle de ce projet.

L’importance d’un SBOM devient alors évidente : il ne sert pas seulement à répondre aux exigences de conformité ou de réglementation imposées par votre équipe Sécurité ou par les autorités. Vous savez désormais que votre projet dépend de 60 packages open source, et pas seulement des deux que vous avez installés directement. C’est tout l’enjeu de la chaîne d’approvisionnement logicielle : ses implications en matière de sécurité sont considérables et représentent des risques directs pour les utilisateurs.

En découvrant que votre projet dépend en réalité de 60 packages open source, vous pourriez vous poser les questions suivantes :

  1. L’un de ces packages est-il soumis à une licence incompatible avec les directives et les usages de mon organisation ?

  2. Tous ces packages font-ils l’objet d’une maintenance active ?

  3. Que se passe-t-il si une nouvelle vulnérabilité est découverte dans l’un de ces 60 packages ?

Voilà le type de problèmes liés à l’état des projets que nous nous efforçons de résoudre avec Snyk Advisor, qui fournit un score de santé tenant compte de la popularité du projet, de sa maintenance, de sa sécurité et des indicateurs liés à sa communauté.

Page Snyk Advisor consacrée au package JavaScript datejs, affichant son score de santé de 53/100 et les détails de son statut.

Pour revenir aux SBOM, voici toutes les options disponibles de la commande permettant d’analyser les projets :

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

Générer un SBOM conforme à la spécification SPDX

La CLI et les points de terminaison de l’API Snyk prennent également en charge la spécification SPDX. En définissant l’option de ligne de commande format sur spdx2.3+json, vous pouvez générer une sortie SBOM conforme à SPDX au format JSON. Voici comment procéder :

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

Vous obtiendrez une sortie similaire à la réponse JSON partielle ci-dessous, issue de notre projet Fastify de référence présenté précédemment :

{
  "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’attendre d’autre d’un SBOM ?

Snyk s’engage à aider les développeurs à créer et à déployer des applications sécurisées, grâce à la détection instantanée de code non sécurisé dans l’IDE et aux demandes de pull automatisées proposant des correctifs pour les dépôts logiciels sur GitHub ou Bitbucket.

Dans cet article, nous nous sommes intéressés aux dépendances des applications JavaScript répertoriées dans un SBOM. Mais celui-ci révèle également d’autres données utiles sur les composants logiciels utilisés dans un projet. Ces informations supplémentaires peuvent être essentielles pour comprendre la composition d’un produit logiciel, mais aussi pour gérer ses risques de sécurité, ses exigences de conformité et ses licences. Voici quelques exemples de données qu’un SBOM peut fournir :

  1. Détails des composants : informations sur chaque composant logiciel, notamment le nom du package npm, sa version et son origine (dépôt npmjs ou dépôt GitHub).

  2. Informations sur les licences : détails sur les licences qui régissent chaque composant logiciel, notamment leur type, leurs conditions et leurs obligations. Vous connaissez peut-être les packages npm sous licence MIT ou Apache, mais une dépendance imbriquée peut utiliser une licence incompatible, telle que GNU GPL, et vous exposer à des risques juridiques.

  3. Données sur les vulnérabilités : informations sur les vulnérabilités de sécurité connues publiquement et associées aux packages npm utilisés dans le logiciel, qu’elles aient un impact direct ou indirect.

  4. Données cryptographiques : informations sur les composants cryptographiques utilisés dans le logiciel, notamment leurs algorithmes et la taille de leurs clés. Par exemple, si une application utilise un algorithme non sécurisé comme le hachage MD5, vous devez le savoir et prendre les mesures nécessaires.

  5. Informations de build : détails sur la façon dont le logiciel a été créé, notamment l’environnement de build, les outils utilisés et les paramètres de configuration.

  6. Métadonnées : informations supplémentaires concernant le logiciel, comme le nom du projet, sa version et son auteur.

Pour illustrer concrètement l’utilité d’un SBOM pour vous, développeur JavaScript, voici un tableau :

Nom du composant

Version

Type de licence

Données sur les vulnérabilités

Données cryptographiques

Express

4.4.0

MIT

S.O.

Lodash

4.17.16

MIT

S.O.

Vue

2.5.16

MIT

S.O.

Axios

0.21.0

MIT

S.O.

À la date de rédaction de cet article, Snyk présente les dépendances et leurs relations dans les formats suivants :

  • CycloneDX version 1.4 en JSON

  • CycloneDX version 1.4 en XML

  • SPDX version 2.3 en JSON

L’équipe travaille à la prise en charge d’autres sections des spécifications, notamment les vulnérabilités, les licences et bien plus encore.

Snyk vous permet également d’utiliser les SBOM d’autres façons :

  • L’outil de vérification des SBOM, un site web gratuit où vous pouvez déposer un artefact SBOM pour que Snyk détecte les vulnérabilités répertoriées dans les packages npm.

  • Section API Snyk sur les SBOM

  • CLI Snyk

  • Approfondissez la documentation utilisateur sur les SBOM

  • Le projet open source Bomber peut lire les spécifications SBOM en entrée et générer une liste de vulnérabilités. Il peut être utile si vous devez travailler avec des composants propriétaires fournis par des éditeurs, et prend également en charge Snyk comme source de données sur les vulnérabilités.

Si vous êtes développeur Java ou si votre organisation a développé des applications basées sur Java, consultez l’article de mon collègue Brian Vermeer sur la création de SBOM en Java avec Maven et Gradle.

Pour une introduction plus détaillée, je vous recommande de lire l’article de Snyk sur les nomenclatures logicielles (SBOM) au service de la sécurité de la chaîne d’approvisionnement open source.

Sécurisez vos dépendances open source

Les outils Snyk, conçus pour les développeurs, génèrent en un clic des pull requests correctives pour vos dépendances open source vulnérables et leurs dépendances transitives.

Lire la suite

blog feature snyk container custom base recommendations
Blog

Découvrez Evo Agentic AppSec : une sécurité au rythme du développement de l’IA

Le développement piloté par l’IA dépasse les workflows de sécurité traditionnels. L’AppSec agentique de Snyk s’appuie sur des agents de sécurité pour détecter, corriger et vérifier les vulnérabilités en continu, tandis que les équipes définissent les exigences.

blog feature ai violet
Blog

VulnBump : les agents IA peuvent-ils corriger les dépendances vulnérables sans casser le build ?

VulnBump évalue des agents IA sur 307 mises à niveau de dépendances réelles. Une correction n’est comptabilisée que si la vulnérabilité disparaît et que la compilation et les tests restent au vert.

Blog

Les modèles de pointe ont trouvé les vulnérabilités. Seul l’attaquant a trouvé les chaînes d’exploitation.

L’analyse statique a détecté les failles, mais seuls des tests d’attaque en conditions réelles ont prouvé comment elles pouvaient être enchaînées pour provoquer des compromissions. Comparaison d’Evo COS, de Claude Security et de Claude Code Security.