npm 11.18.0, publiée le 29 juin 2026, est la release qui achève le travail que le CLI npm mène sur les installations isolées depuis trois ans et demi. L'événement phare est la PR #9677 (backport de #9674), qui fait passer --install-strategy=linked d'expérimental à stable. Le mode avait été ajouté dans la PR #6078 le 25 janvier 2023 contre la npm/rfcs#0042, la RFC sur le mode isolated issue du Contributor Summit 2022. La promotion retire l'avertissement implicite « ceci peut dévorer votre node_modules » que la doc portait depuis 2023 et constitue l'événement de clôture du plus long effort de l'équipe npm sur les stratégies d'installation.
La release est la deuxième release de fonctionnalité de la ligne v11 ce mois-ci et accompagne la prerelease npm v12 que l'équipe a taguée le même jour. La ligne v11 est la ligne stable ; la prerelease v12 est l'endroit où le changement block-unreviewed-install-scripts-by-default et la promotion du mode linked sont ré-appliqués contre la future major.
Ce que --install-strategy=linked change concrètement
La stratégie d'installation par défaut de npm est hoisted. Chaque dépendance transitive est dupliquée dans le node_modules racine pour que tout paquet puisse require n'importe quelle dépendance transitive hissée par hasard, même si rien dans son package.json ne la déclare. C'est la cause racine des dépendances fantômes : du code qui importe une bibliothèque jamais ajoutée à ses propres dependencies, et le bug n'apparaît que lorsqu'un collègue installe avec un node_modules propre et que le hissage se trouve différent.
--install-strategy=linked (aussi appelée mode isolated) installe en revanche chaque paquet dans node_modules/.store/<name>@<version>/node_modules/<dep> et lie symboliquement les dépendances déclarées de chaque paquet dans son propre node_modules/<dep>. Résultat : un paquet ne peut import que ce qu'il a déclaré. S'il importe une bibliothèque non déclarée, l'import échoue immédiatement au lieu de fonctionner par accident et de partir en prod cassé.
La doc npm install décrit les quatre stratégies ainsi :
hoisted(défaut) : installe non-dupliqué au niveau racine, dupliqué si nécessaire au sein de la structure de répertoires.nested(anciennement--legacy-bundling) : installe en place, sans hissage.shallow(anciennement--global-style) : n'installe que les deps directes au niveau racine.linked: installe dansnode_modules/.store, lie en place, pas de hissage.
Les notes de release de la 11.18 ajoutent la recommandation de doc qui fait de la stratégie une vraie recommandation plutôt qu'un flag CLI caché. La page de doc dit désormais : « Nous recommandons aux auteurs de paquets d'utiliser --install-strategy=linked pendant le développement pour intercepter les dépendances non déclarées (phantom) avant publication : le layout isolated n'expose que les dépendances déclarées du paquet, donc un import d'un paquet qui n'a jamais été ajouté au package.json peut échouer au lieu de se résoudre par accident et de partir cassé. Voir Catching undeclared (phantom) dependencies. »
Cette phrase a été ajoutée par la PR #9690, le changement de doc qui backporte en parallèle de la promotion.
Pourquoi trois ans et demi en expérimental
Trois raisons. D'abord, le drapeau expérimental s'accompagnait d'angles tranchants. Le ticket de suivi #9608 de l'équipe ([Tracking] install-strategy=linked (isolated mode) bugs) liste 19 bugs distincts à travers le chemin d'install, le chemin d'audit, le chemin npm exec et le chemin npm ls que la release 11.18 referme. Les quatre que l'équipe a signalés comme les pires sont l'audit qui renvoie zéro résultat sur une vulnérabilité réelle (#9609), npm ls qui reporte de faux UNMET DEPENDENCY (#9095), napi-postinstall qui ne résout pas une liaison native optionnelle installée (#9620), et le mismatch de layout .store avec le lockfile caché (#9612). Les fixes 11.18 pour chacun sont les PRs #9638, la suite de #9095 sous la logique de #9638, le fix de #9620 sous #9665, et #9642 respectivement.
Ensuite, la stratégie avait besoin d'une histoire d'audit. La PR #9625 audit l'arbre non-isolé sous la stratégie linked, de sorte que npm audit parcourt à la fois la vue linked et le store sous-jacent et reporte les vulnérabilités correctement. La PR #9638 rend le rapport d'audit déterministe en rattachant les liens via perdus, pour que deux exécutions consécutives de npm audit sur un lockfile inchangé produisent une sortie octet-identique, ce dont l'infrastructure CI de l'équipe dépend pour les tests de régression basés sur diff.
Enfin, l'histoire workspace. Les PR #9666 et #9665 apprennent à la stratégie linked à charger les dépendances optionnelles transitives et à appliquer correctement les drapeaux dev/prod au sein des workspaces ; #9648 fait que npm exec résout les bins locaux au workspace ; #9669 surface les workspaces non déclarés sous la stratégie linked pour qu'une entrée workspaces manquante ne produise pas silencieusement une install partielle. Avant la 11.18, la stratégie linked fonctionnait pour les repos mono-paquet mais trébuchait sur les setups workspaces ; après la 11.18, c'est le pilote quotidien recommandé pour les workspaces.
Le nouvel espace de noms npm install-scripts
La PR #9635 (backport de #9629) introduit une commande à espace de noms npm install-scripts qui possède trois sous-commandes : npm install-scripts approve, npm install-scripts deny, et npm install-scripts ls. Les anciennes commandes npm approve-scripts et npm deny-scripts sont conservées comme alias pour une release, puis retirées. Le namespace ré-oriente les instructions d'install, de rebuild et de strict-allow-scripts vers les nouvelles commandes, pour qu'un développeur qui exécute npm install et tombe sur la nouvelle ligne « npm install blocked N scripts » soit renvoyé vers la même famille de commandes.
La raison d'être du namespace est que approve-scripts était une commande cas spécial posée à côté du reste de la surface de commandes npm ; install-scripts la fait entrer dans la même famille que install, install-test, etc. Cela donne aussi à l'équipe la place d'ajouter des sous-commandes : npm install-scripts ls est nouveau en 11.18 et imprime la liste allow/deny courante avec les noms de paquets et les chemins.
La release ajoute aussi la PR #9662 (install-scripts: prune unused allowScripts entries), qui balaie la liste d'allow à chaque install et retire les entrées dont le paquet n'est plus dans dependencies. Cela referme un défaut de longue date où la liste d'allow croissait monotonement : si vous approuviez esbuild pour package-a, puis retiriez esbuild des deps de package-a et l'ajoutiez à celles de package-b, la liste d'allow gardait l'entrée d'origine. Après la 11.18, le sweep la retire dans npm install, et l'utilisateur est invité à réapprouver sous package-b.
L'avertissement min-release-age sur l'audit fix
La PR #9564 (backport de #9544) apprend à npm audit fix à détecter quand le correctif qu'il appliquerait est bloqué par la policy minimumReleaseAge configurée dans .npmrc. La même policy est livrée par pnpm, et le flux de mise à jour d'Astro 6.4.4 la surface pour @astrojs/upgrade. La version npm avertit explicitement quand la policy bloque un correctif d'audit, au lieu de ne rien faire en silence :
npm audit fix
# 3 vulnerabilities (1 low, 1 moderate, 1 high)
#
# Could not auto-fix 1 vulnerability:
# package: glob-parent <6.0.0 (transitive via some-tool)
# blocked by minimumReleaseAge=4320 (cool-down window)
# set `minimum-release-age=0` or wait for the cool-down to expire.
Le texte a la même forme que l'avertissement ERR_PNPM_MIN_RELEASE_AGE de pnpm. La description de PR de l'équipe npm dit qu'elle « veut que les utilisateurs puissent faire la différence entre « pas de correctif disponible » et « correctif existant mais retenu par la policy » », ce que la sortie précédente de npm audit fix ne permettait pas.
SBOM et autres corrections
Trois fixes npm sbom sont livrés en 11.18. La PR #9693 encode en pourcentage le qualificateur vcs_url dans les purls générées, ce qui referme un bug de longue date de l'outillage CP où une URL git+https://github.com/foo bar/bar (avec un espace) était émise verbatim et rejetée par les parseurs en aval. La #9631 audit l'arbre non-isolé sous la stratégie linked pour que les rapports SBOM et npm audit remontent tous les deux le jeu complet de deps. La #9641 valide les conflits peerOptional dans les mutations no-save, ce qui signifie que npm install some-pkg --no-save refusera d'installer si cela créerait un conflit peerOptional.
La release corrige aussi la PR #9602 (ne pas signaler les deps optionnelles inertes en strict-allow-scripts), la #9607 (approuver par nom les deps sans URL résolue), et la #9663 (refermer les failles d'enforcement allowScripts). Prises ensemble, elles signifient que le mode strict-allow-scripts ajouté dans npm 11.5 distingue maintenant correctement les paquets qui ont besoin de scripts (le hook d'install est actif, le hook d'audit les attrapera) et ceux qui n'en ont pas (le hook d'install est désactivé parce qu'il n'y a pas de script d'install).
Pourquoi c'est important
--install-strategy=linked est la réponse de npm à la question à laquelle pnpm répond depuis 2017 : comment empêcher un paquet d'importer une dépendance transitive qu'il n'a jamais déclarée ? pnpm n'a jamais porté le drapeau expérimental ; yarn berry livre PnP par défaut ; npm est le troisième des trois à atteindre le statut « stable et recommandé pour l'usage quotidien ». La promotion est le moment où le modèle d'installation que tous les autres traitent comme défaut devient enfin un chemin recommandé par défaut chez npm.
Pour les auteurs de paquets, le changement concret est petit et précis. Ajoutez ceci à .npmrc :
install-strategy=linked
Puis exécutez npm install en CI dans le cadre du npm publish. Si le build échoue maintenant parce qu'un fichier de test importe une bibliothèque non déclarée, vous avez un vrai bug à corriger avant publication, pas une dépendance fantôme qui explosera sur l'install propre d'un collègue.
Le même changement s'applique aux propriétaires de monorepos. Les fixes 11.18 pour npm exec (#9648), npm ls (#9664), les workspaces (#9666), et le nettoyage .store au changement de stratégie (#9649) referment les failles qui rendaient --install-strategy=linked inutilisable pour les workspaces avant. Un monorepo peut livrer install-strategy=linked dans .npmrc à la racine et compter sur sa propagation dans les workspaces.
La release est aussi la première depuis l'article supply chain du 6 juin qui referme les failles d'audit strict-allow-scripts mentionnées dans cet article. Les drapeaux --install-blocked-scripts et strict-allow-scripts de npm 11.5 sont maintenant utilisables de bout en bout, et le nouvel espace de noms npm install-scripts est l'endroit où vivent les approbations.



