---
title: "pnpm 11.8 livre `install --dry-run`, des package maps Node.js et une SBOM par paquet"
description: "pnpm 11.8.0 (18 juin 2026) ajoute un `--dry-run` longtemps réclamé pour `pnpm install`, des package maps Node.js expérimentales dans `node_modules/.package-map.json`, le scope CycloneDX pour les devDependencies et la génération de SBOM par paquet, ainsi qu'un correctif macOS Gatekeeper qui retire la quarantaine des binaires natifs. Il corrige aussi une faille de traversal de chemin sur les configDependencies (GHSA-qrv3-253h-g69c) trois jours après le durcissement du lockfile en 11.7."
date: 2026-06-19
image: "/images/heroes/2026-06-19--pnpm-11-8-dry-run-install-node-package-map-sbom.png"
author: lschvn
tags: ["tooling", "security", "ecosystem"]
tldr:
  - "pnpm 11.8.0 (18 juin 2026) ajoute `pnpm install --dry-run`, qui exécute une résolution complète des dépendances et indique ce qu'une installation modifierait sans rien écrire sur le disque, ni lockfile, ni `node_modules`, et quitte toujours avec le code 0. Il reproduit le comportement de `npm install --dry-run` et clôture [l'issue #7340](https://github.com/pnpm/pnpm/issues/7340), ouverte depuis 2022."
  - "Deux améliorations SBOM arrivent pour la conformité de la chaîne d'approvisionnement : `pnpm sbom` marque désormais les composants accessibles uniquement via les devDependencies avec le scope CycloneDX `scope: \"excluded\"` et la propriété `cdx:npm:package:development`, et `--out`/`--split` produisent un document CycloneDX par paquet du workspace en résolvant les inter-dépendances `workspace:`. Un nouveau fichier `node_modules/.package-map.json` alimente les travaux expérimentaux de résolution de paquets de Node derrière `node-experimental-package-map`."
  - "La version corrige également une traversal de chemin sur les configDependencies (GHSA-qrv3-253h-g69c), où un lockfile contenant un nom ou une version mal formés pouvait écrire des fichiers en dehors de `node_modules/.pnpm-config`, et retire la quarantaine macOS Gatekeeper des binaires natifs après l'import depuis le store."
faq:
  - question: "Quoi de neuf dans pnpm 11.8 ?"
    answer: "pnpm 11.8.0 (18 juin 2026) livre `pnpm install --dry-run` pour prévisualiser les installations sans écrire sur le disque, des package maps Node.js expérimentales dans `node_modules/.package-map.json`, le scope CycloneDX `scope: \"excluded\"` pour les devDependencies dans `pnpm sbom`, la génération de SBOM par paquet via `--out` et `--split`, un correctif macOS Gatekeeper qui retire la quarantaine des binaires natifs, et un correctif de sécurité pour la traversal de chemin sur les configDependencies (GHSA-qrv3-253h-g69c). Il requiert Node.js 22.13 ou supérieur."
  - question: "Comment fonctionne `pnpm install --dry-run` ?"
    answer: "Il exécute une résolution complète des dépendances et affiche ce qu'une installation ajouterait, supprimerait ou modifierait, sans rien écrire sur le disque : ni `pnpm-lock.yaml`, ni `node_modules`. Il quitte toujours avec le code 0, ce qui correspond à la sémantique de `npm install --dry-run`. C'est utile pour valider un changement de manifeste ou un diff de dépendances d'une branche en CI sans muter le répertoire de travail."
  - question: "Qu'est-ce que la vulnérabilité de traversal sur les configDependencies dans pnpm ?"
    answer: "GHSA-qrv3-253h-g69c : avant la 11.8, un lockfile dont les `configDependencies` contenaient un nom (par exemple `../../PWNED`) ou une version de type traversal pouvait provoquer une écriture de liens symboliques ou de fichiers de paquet en dehors de `node_modules/.pnpm-config` et du store lors d'un `pnpm install`. Le correctif valide que les noms sont des noms de paquet npm valides et que les versions sont du semver exact avant de les utiliser pour construire des chemins, et applique la même vérification aux sous-dépendances optionnelles des configDependencies ainsi qu'au format legacy des manifestes de workspace."
  - question: "Que sont les package maps Node.js dans pnpm 11.8 ?"
    answer: "pnpm 11.8 peut générer un fichier `node_modules/.package-map.json` lors des installations isolated (par défaut) et hoisted. Deux paramètres le contrôlent : `node-experimental-package-map` injecte la carte générée dans les environnements de script Node.js gérés par pnpm, et `node-package-map-type` choisit entre un format `standard` et `loose`. La carte alimente les travaux en cours de Node sur une résolution de paquets plus rapide et plus prévisible."
  - question: "pnpm 11.8 casse-t-il mon projet existant ?"
    answer: "Non. Le format du lockfile est inchangé. `--dry-run`, les paramètres de package map et les drapeaux SBOM sont opt-in. La validation des configDependencies ne rejette que des noms et versions qui n'auraient jamais dû être valides. Le seul changement de comportement que la plupart des équipes remarqueront est que `pnpm run --no-bail` quitte désormais avec un code non nul quand un script échoue, ce qui rend les exécutions non récursives cohérentes avec les récursives qui se comportaient déjà ainsi."
  - question: "Que fait le correctif macOS Gatekeeper ?"
    answer: "Quand pnpm importe des binaires natifs (`.node`, `.dylib`, `.so`) depuis son store à adressage de contenu vers `node_modules`, macOS préserve les attributs étendus, dont `com.apple.quarantine`. Si cet xattr était présent sur un blob du store, il se propageait vers `node_modules` et Gatekeeper bloquait le binaire natif au chargement, même si pnpm avait déjà vérifié l'intégrité du fichier. pnpm 11.8 retire désormais `com.apple.quarantine` des binaires natifs après l'import, reproduisant le comportement de Homebrew, via un seul appel `xattr` groupé par paquet."
---

[pnpm 11.8.0](https://github.com/pnpm/pnpm/releases/tag/v11.8.0) est sorti le 18 juin 2026, trois jours après [11.7.0](https://github.com/pnpm/pnpm/releases/tag/v11.7.0), la version qui ajoutait `--frozen-store`, la délégation de résolution à pacquet et [un correctif de traversal de chemin dans le lockfile](/articles/2026-06-17-pnpm-11-7-frozen-store-publish-batch). Là où la 11.7 portait sur les installations reproductibles et en lecture seule, la 11.8 vise l'observabilité et le reporting de chaîne d'approvisionnement : un mode dry-run qui reproduit enfin npm, un format de package map Node.js qui alimente les expériences de résolution du runtime, et deux améliorations CycloneDX SBOM qui rendent `pnpm sbom` utilisable pour de vrais workflows de conformité. On trouve aussi un second avis de traversal de chemin, cette fois dans `configDependencies`, et un correctif macOS Gatekeeper qui agaçait les utilisateurs de modules natifs depuis un moment.

## `pnpm install --dry-run` : la fonctionnalité que npm avait et pas pnpm

L'ajout principal est `--dry-run` pour `pnpm install`. Il exécute une résolution complète des dépendances contre les manifestes courants et affiche ce qu'une installation ajouterait, supprimerait ou modifierait, puis n'écrit rien : ni `pnpm-lock.yaml`, ni `node_modules`, ni mutation du store. Il quitte toujours avec le code 0, ce qui correspond à la sémantique de [`npm install --dry-run`](https://docs.npmjs.com/cli/v10/commands/npm-install#dry-run) et clôture [l'issue #7340](https://github.com/pnpm/pnpm/issues/7340), ouverte depuis 2022.

L'usage pratique est la CI et la revue de code : une PR qui monte une dépendance ou change une entrée de catalogue peut lancer `pnpm install --dry-run` pour exposer le diff transitif complet, y compris les avertissements de peer et les approbations de build-script, sans toucher au répertoire de travail. Comme la résolution de pnpm est déjà rapide, le coût est une passe de résolution sans écriture sur le système de fichiers. Le code de sortie est volontairement toujours 0 pour que le drapeau puisse s'insérer dans une étape d'installation existante sans faire passer un pipeline au rouge sur un diff bénin.

## Package maps Node.js dans `node_modules/.package-map.json`

La 11.8 peut désormais générer un `node_modules/.package-map.json` lors des installations isolated (par défaut) et hoisted. Deux paramètres contrôlent le comportement :

- `node-experimental-package-map` : quand il est activé, pnpm injecte la carte générée dans les environnements de script Node.js qu'il gère, afin que le runtime puisse consulter une disposition de paquets précalculée au lieu de parcourir `node_modules` au démarrage.
- `node-package-map-type` : choisit entre une carte `standard` et une carte `loose`, au prix d'un compromis entre rigueur et compatibilité.

C'est une plomberie précoce pour la [réforme de résolution de paquets de Node](https://github.com/nodejs/node/pulls?q=package+map), où un fichier de carte déclaratif pourrait remplacer la résolution implicite et pilotée par le système de fichiers que chaque gestionnaire de paquets doit actuellement contourner. Le fait que pnpm génère la carte signifie que les projets qui l'activent obtiennent une description de disposition cohérente, qu'ils utilisent le linker isolated ou hoisted. Le nom du paramètre (`node-experimental-package-map`) signale que le format n'est pas encore stable.

## SBOM : le scope des devDependencies et la génération par paquet

Les deux changements SBOM de la 11.8 ciblent l'écart entre un arbre de dépendances et ce dont un consommateur CycloneDX peut réellement déduire.

Premièrement, `pnpm sbom` marque désormais les composants accessibles uniquement via les `devDependencies` avec le scope CycloneDX `scope: "excluded"` et la propriété `cdx:npm:package:development`. Le scope `excluded` est la façon CycloneDX de documenter « l'usage d'un composant à des fins de test et autres usages non runtime », ce qui correspond exactement à une devDependency. La propriété reproduit le marqueur qu'émet [`@cyclonedx/cyclonedx-npm`](https://www.npmjs.com/package/@cyclonedx/cyclonedx-npm), donc les consommateurs modernes (basés sur le scope) et existants (basés sur la propriété) le récupèrent tous les deux. Les composants accessibles au runtime, y compris les `optionalDependencies` installées, omettent le `scope` et valent `required` par défaut.

Deuxièmement, la génération de SBOM par paquet arrive via deux drapeaux :

- `--out out/%s.cdx.json` écrit un document CycloneDX par paquet du workspace dans des fichiers individuels.
- `--split` émet du NDJSON sur stdout, un paquet par ligne.

Quand `--filter` sélectionne un seul paquet, le composant racine de la SBOM utilise désormais les métadonnées de ce paquet. Les inter-dépendances du workspace déclarées via le protocole `workspace:`, ainsi que leurs dépendances transitives, sont incluses pour qu'une SBOM par paquet soit autonome. L'auteur, le dépôt et la licence reviennent au manifeste racine quand le paquet ne les définit pas. Pour un monorepo qui doit livrer une SBOM par bibliothèque publiée, c'est la différence entre post-traiter un document géant et obtenir des artefacts par paquet directement depuis l'outil d'installation.

## Traversal de chemin sur les configDependencies (GHSA-qrv3-253h-g69c)

La 11.8 corrige un second avis de traversal de chemin, distinct du [correctif d'alias de lockfile en 11.7](/articles/2026-06-17-pnpm-11-7-frozen-store-publish-batch) et de la [traversal Windows d'esbuild 0.28.1](/articles/2026-06-14-esbuild-0-28-1-deno-rce-windows-path-traversal) qui avait surfaced dans un autre outil. Avant la 11.8, un lockfile dont les `configDependencies` contenaient un nom (par exemple `../../PWNED`) ou une version (par exemple `../../../PWNED`) de type traversal pouvait provoquer une écriture de liens symboliques ou de fichiers en dehors de `node_modules/.pnpm-config` et du store lors d'un `pnpm install`.

Le correctif valide les noms et versions des `configDependencies` avant qu'ils ne soient utilisés pour construire des chemins. Les noms doivent désormais être des noms de paquet npm valides et les versions des chaînes semver exactes. La même validation s'applique aux sous-dépendances optionnelles des configDependencies et au format legacy des manifestes de workspace, avant toute écriture du lockfile. Comme la porte de vérification de la 11.7, c'est une défense en profondeur : un projet qui fait déjà confiance à sa source de lockfile en bénéficie quand même, car la vérification protège contre la corruption partielle et contre les bugs dans le générateur de lockfile lui-même. Voir [GHSA-qrv3-253h-g69c](https://github.com/pnpm/pnpm/security/advisories/GHSA-qrv3-253h-g69c).

## macOS Gatekeeper ne bloque plus les binaires natifs

Un correctif plus discret mais largement ressenti : quand pnpm importe des fichiers depuis son store à adressage de contenu vers `node_modules`, macOS préserve les attributs étendus, dont `com.apple.quarantine`. Si cet xattr était présent sur un blob du store (par exemple, il a d'abord été écrit sous une application Gatekeeper-activée comme un client Git), il se propageait vers `node_modules`, et Gatekeeper bloquait le binaire natif au chargement même si pnpm avait déjà vérifié l'intégrité du fichier contre le lockfile.

Après l'import d'un paquet, la 11.8 retire désormais `com.apple.quarantine` des binaires natifs (`.node`, `.dylib`, `.so`), reproduisant [le comportement de Homebrew](https://docs.brew.sh/FAQ#why-cant-i-open-a-mac-app-from-an-unidentified-developer) qui retire la quarantaine des téléchargements vérifiés. Le nettoyage est réservé à macOS, s'exécute en un seul appel `xattr` groupé par paquet, se limite aux binaires natifs pour que les autres fichiers restent intacts, et est non bloquant. Il corrige [#11056](https://github.com/pnpm/pnpm/issues/11056).

## Autres correctifs à connaître

`pnpm run --no-bail` quitte désormais avec un code non nul quand un script exécuté échoue, tout en continuant à exécuter tous les scripts correspondants jusqu'au bout. Cela clôture [l'issue #8013](https://github.com/pnpm/pnpm/issues/8013) : les exécutions `--no-bail` non récursives quittaient toujours avec 0 même en cas d'échec, ce qui était incohérent avec les exécutions récursives qui échouaient déjà à la fin.

`pnpm view` sans nom de paquet cherche désormais vers le haut le manifeste de projet le plus proche (`package.json`, `package.yaml` ou `package.json5`) et utilise son champ `name`, remplaçant la dépendance `find-up` par le module [`empathic`](https://www.npmjs.com/package/empathic), plus rapide. Plusieurs bugs de correction du lockfile arrivent aussi : les installations incrémentales ne conservent plus les dépendances transitives dupliquées qu'une installation fraîche n'aurait pas produites ([#5108](https://github.com/pnpm/pnpm/issues/5108)), `optimisticRepeatInstall` ne signale plus « Already up to date » quand seul le lockfile a changé ([#12100](https://github.com/pnpm/pnpm/issues/12100)), et les overrides de catalogue qui se résolvent via un catalogue restent synchronisés avec le catalogue pendant `pnpm update`. `pnpm version --recursive` respecte désormais le filtre de workspace au lieu de monter chaque paquet ([#11348](https://github.com/pnpm/pnpm/issues/11348)). La sortie du reporter pour `pnpm store` et `pnpm config` va désormais sur stderr, pour que des scripts comme `PNPM_STORE=$(pnpm store path)` ne capturent plus d'avertissements dans leur résultat.

## Mise à niveau

pnpm 11.8.0 requiert Node.js 22.13 ou supérieur, la même ligne de base que la 11.7. Le format du lockfile est inchangé, donc un `npm install -g pnpm@latest` (ou `corepack prepare pnpm@latest --activate`) suivi d'un `pnpm install` constitue le chemin complet de mise à niveau. Les nouveaux drapeaux sont tous opt-in, et la validation des configDependencies ne rejette que des entrées qui n'ont jamais été des noms de paquet valides.
