123% de CVE signalées en plus par jour en 2026 par rapport à l'an dernier.

Dépendances

Qu'est-ce qu'une dépendance transitive ?

Une dépendance transitive est un paquet que votre logiciel utilise parce qu'un autre paquet en a besoin. Vous ne l'avez jamais déclarée, mais elle fait partie de ce que vous livrez, avec ses propres vulnérabilités et sa licence. Voici comment les voir, les corriger et prouver lesquelles sont entrées dans chaque release.

Mis à jour le

A vulnerable transitive dependency and its fix path An app declares two direct dependencies, express and hbs. Express brings in body-parser and send, which bring in raw-body and mime-types. Hbs brings in handlebars, which is vulnerable. The path from the app through hbs to handlebars is highlighted: upgrade hbs, or override the handlebars version. your project direct transitive, depth 1 depth 2 my-app express hbs body-parser send handlebars vulnerable, required by hbs raw-body mime-types Fix path: upgrade hbs, or override the handlebars version

Dépendances directes et transitives

Une dépendance directe est une dépendance que vous déclarez dans votre manifeste. Une dépendance transitive est une dépendance que vos dépendances déclarent, et ainsi de suite, aussi loin que s'étend l'arbre. Le gestionnaire de paquets résout tout l'arbre à l'installation et enregistre généralement le résultat dans un lockfile.

Prenons une application qui déclare un seul paquet, express. Exécuter npm ls --all montre ce que cette seule ligne entraîne :

my-app
└─┬ express            ← directe : vous l'avez déclarée
  ├─┬ body-parser      ← transitive, profondeur 1
  │ └── raw-body       ← transitive, profondeur 2
  ├── cookie           ← transitive, profondeur 1
  └─┬ send             ← transitive, profondeur 1
    └── mime-types     ← transitive, profondeur 2

L'arbre réel est plus long. La plupart des paquets d'une application typique arrivent ainsi : l'essentiel du code que vous livrez a donc été choisi par le gestionnaire de paquets, et non par vous.

Dépendance directe Dépendance transitive
Qui l'a choisie Votre équipe, dans le manifeste Le gestionnaire de paquets, d'après les manifestes de vos dépendances
Où elle est listée Manifeste et lockfile Lockfile, s'il y en a un
Qui contrôle la version Vous La plage de versions du paquet parent, sauf si vous la remplacez
Comment corriger une vulnérabilité La mettre à niveau Mettre à niveau le parent, ou forcer la version

Pourquoi les dépendances transitives sont importantes

Elles présentent les mêmes risques que les dépendances directes, avec moins de visibilité et moins de contrôle.

  • Les vulnérabilités. Lorsque Log4Shell, une zero-day dans log4j, a été divulguée, l'équipe Open Source Insights de Google a trouvé 35 863 artefacts Maven Central qui dépendaient du code log4j concerné. Environ 7 000 en dépendaient directement. La majorité l'entraînait en tant que dépendance transitive, et beaucoup n'ont pu être corrigés qu'après qu'un paquet intermédiaire a d'abord livré un correctif.
  • Attaques de la chaîne d'approvisionnement. La porte dérobée de xz utils (CVE-2024-3094) a atteint OpenSSH sans qu'OpenSSH dépende de xz. Plusieurs distributions Linux modifient OpenSSH pour prendre en charge les notifications systemd, et libsystemd dépend de liblzma, la bibliothèque fournie par xz.
  • Les licences. Chaque paquet transitif a sa propre licence. Une licence copyleft trois niveaux plus bas est aussi contraignante que celle d'un paquet que vous avez ajouté vous-même.
  • Les changements incompatibles. Un paquet parent qui accepte une plage de versions laisse entrer une nouvelle release transitive à la prochaine installation à neuf, même si rien n'a changé dans votre manifeste.

Comment lister vos dépendances transitives

Tous les grands gestionnaires de paquets peuvent afficher l'arbre résolu :

Écosystème Commande
npmnpm ls --all
pnpmpnpm list --depth Infinity
Python (uv)uv tree
Python (pip)pipdeptree
Gogo mod graph
Rustcargo tree
Mavenmvn dependency:tree
Gradlegradle dependencies

Pour savoir pourquoi un paquet précis est là, demandez le chemin qui y mène : npm explain <package>, pnpm why, yarn why ou cargo tree -i <crate>. Pour travailler sur les chemins au lieu de simplement les afficher, voir les graphes de dépendances.

Comment corriger une dépendance transitive vulnérable

  1. Mettez à niveau le parent. Trouvez la dépendance directe qui entraîne le paquet et passez à une release qui exige une version corrigée. C'est la correction la plus propre, car les mainteneurs du parent l'ont testée.
  2. Actualisez le lockfile. Si la plage de versions du parent autorise déjà la version corrigée, il suffit de mettre à jour l'entrée du lockfile, par exemple avec cargo update -p <crate> ou un nouveau npm update.
  3. Forcez la version. Si le parent n'a pas livré de correctif, imposez la version vous-même : overrides dans npm et pnpm, resolutions dans Yarn, un fichier de contraintes avec pip, ou une exigence plus élevée dans go.mod. Testez-la, car le parent n'a jamais été publié avec cette version.
  4. Remplacez ou retirez le parent. Si rien de cela ne fonctionne, la dépendance qui amène le paquet ne vaut peut-être plus la peine d'être conservée.

Certains outils d'analyse de la composition logicielle ajoutent l'analyse d'atteignabilité, qui vérifie si votre code peut effectivement appeler la fonction vulnérable, pour décider laquelle de ces corrections passe en premier. Voir le comparatif des outils SCA pour les options.

Pourquoi le lockfile ne dit pas tout

La plupart des outils construisent leur vue des dépendances transitives à partir du lockfile. Cela fonctionne lorsque le lockfile est présent, à jour et qu'il est la seule source d'installation du build. En CI, ce n'est souvent pas le cas :

  • Pas de lockfile. Un requirements.txt avec des plages de versions ou un projet qui n'a jamais commité son lockfile est résolu à neuf à chaque build : les versions transitives peuvent donc changer d'un build à l'autre.
  • Les caches. Les caches CI restaurent des paquets issus d'exécutions antérieures au lieu de les récupérer, et leur contenu ne correspond pas toujours à ce que dit le lockfile actuel. Voir ce que le cache GitHub Actions dissimule.
  • Les outils de build. Les linters, les compilateurs, les générateurs de code et les étapes de configuration apportent leurs propres arbres de dépendances dans le build. Ils ne figurent pas dans le manifeste de votre application, mais ils s'exécutent avec un accès à votre code source et à vos secrets.
  • Les scripts d'installation et les téléchargements. Le script d'installation d'un paquet peut récupérer davantage de code, et une étape de build peut télécharger directement un binaire. Ni l'un ni l'autre ne laisse d'entrée dans un lockfile.

Le seul enregistrement complet des dépendances transitives entrées dans une release est celui réalisé pendant le build de cette release. Les SBOM au build expliquent la différence entre enregistrer un build et scanner ses fichiers après coup.

Les dépendances transitives et le CRA

Le Cyber Resilience Act de l'UE demande aux fabricants d'établir une SBOM couvrant « au minimum les dépendances de niveau supérieur des produits » (annexe I, partie II, point 1). Les dépendances transitives ne sont pas citées : le minimum légal est donc plus bas que ne le suggèrent de nombreux guides. Mais le CRA vous demande aussi d'identifier et de traiter les vulnérabilités des composants que contient votre produit, et un paquet transitif vulnérable en fait partie. Une SBOM qui s'arrête au premier niveau laisse l'essentiel de votre arbre de dépendances hors de ce processus. Voir les exigences du CRA sur les SBOM pour les détails.

Comment CRACI suit les dépendances transitives

CRACI est un runner GitHub Actions qui enregistre le build au lieu de le scanner. Pendant l'exécution de chaque job, un proxy qui comprend les paquets enregistre chaque paquet récupéré par le job, à tous les niveaux de l'arbre, y compris les paquets restaurés depuis les caches CI. Cela donne une vue plus complète des dépendances utilisées que les outils basés sur des scanners.

  • Tous les niveaux, en toute transparence. La SBOM de chaque job comporte un état de complétude : vous savez ainsi quand un enregistrement n'a pas pu tout voir.
  • L'arbre, visible. Un graphe de dépendances montre les couches de dépendances de la SBOM, selon plusieurs vues.
  • Des exports qui les incluent. Les exports CycloneDX et SPDX incluent les dépendances transitives, chacune avec sa licence déclarée.
  • Quels builds ont été touchés. Lorsqu'une nouvelle vulnérabilité apparaît, l'historique des builds montre quels builds passés contenaient le paquet vulnérable, direct ou transitif : vous connaissez ainsi la période pendant laquelle vous l'avez livré (voir sommes-nous touchés par une CVE ?). L'historique suit votre durée de conservation, 180 jours par défaut.
  • Des gates de politique. Un build qui contient une CVE précise peut être bloqué avant d'être livré.

CRACI ne fait pas d'analyse d'atteignabilité. Si vous devez savoir si votre code appelle une fonction vulnérable, associez-le à un outil SCA qui en fait. Voir la génération de SBOM dans CRACI ou réservez une démo pour enregistrer l'un de vos propres builds.

Dépendances transitives : questions fréquentes

Qu'est-ce qu'une dépendance transitive ?

Une dépendance transitive est un paquet que votre logiciel utilise parce qu'un autre paquet en a besoin. Si votre application dépend de la bibliothèque A et que A dépend de la bibliothèque B, alors B est une dépendance transitive, ou indirecte, de votre application. Vous ne l'avez jamais déclarée, mais elle est livrée avec votre logiciel.

Quelle est la différence entre une dépendance directe et une dépendance transitive ?

Une dépendance directe est une dépendance que vous déclarez dans votre manifeste, tel que package.json, pyproject.toml ou go.mod. Une dépendance transitive est une dépendance que vos dépendances directes déclarent, à n'importe quelle profondeur. Vous choisissez les dépendances directes ; le gestionnaire de paquets choisit les transitives lorsqu'il résout l'arbre.

Une dépendance transitoire est-elle la même chose qu'une dépendance transitive ?

Oui, en pratique. « Dépendance transitoire » est un lapsus courant pour « dépendance transitive ». Le terme correct est transitive, d'après la relation transitive : si A dépend de B et que B dépend de C, alors A dépend de C.

Comment corriger une vulnérabilité dans une dépendance transitive ?

Mettez d'abord à niveau la dépendance directe qui l'entraîne, si une release avec une version corrigée existe. Sinon, imposez la version corrigée avec le mécanisme de forçage de votre gestionnaire de paquets, comme les overrides de npm, les resolutions de Yarn ou un fichier de contraintes pip, et vérifiez que le paquet parent fonctionne toujours avec elle.

Comment lister toutes les dépendances transitives ?

Tous les gestionnaires de paquets peuvent afficher l'arbre résolu : npm ls --all, pnpm list --depth Infinity, uv tree ou pipdeptree, go mod graph, cargo tree, mvn dependency:tree ou gradle dependencies. Pour savoir ce qu'un build de production a réellement installé, enregistrez le build lui-même.

Le Cyber Resilience Act de l'UE exige-t-il les dépendances transitives dans la SBOM ?

Le règlement fixe le seuil à « au minimum les dépendances de niveau supérieur des produits » (annexe I, partie II, point 1). Les dépendances transitives ne sont pas citées, mais un paquet transitif vulnérable fait tout de même partie de votre produit, et le CRA vous demande de gérer les vulnérabilités des composants que vous livrez.

Voyez chaque dépendance récupérée par votre build

Exécutez un workflow GitHub Actions sur CRACI et obtenez une SBOM enregistrée de chaque paquet récupéré, à tous les niveaux de l'arbre.

Réserver une démo