Your internal npm packages have names. If those names are not registered on the public npm registry, an attacker can register them right now — with a higher version number — and wait. The next time a developer on your team runs npm install without a properly configured .npmrc, npm will silently pull the attacker's public package instead of your private one. No exploit required. No CVE. Just a naming collision and a mismatched registry configuration.

Vos packages npm internes ont des noms. Si ces noms ne sont pas enregistrés sur le registry npm public, un attaquant peut les enregistrer maintenant — avec un numéro de version plus élevé — et attendre. La prochaine fois qu'un développeur de votre équipe lance npm install sans un .npmrc correctement configuré, npm téléchargera silencieusement le package public de l'attaquant plutôt que le vôtre. Aucun exploit requis. Aucune CVE. Juste une collision de noms et une mauvaise configuration de registry.

This is dependency confusion — first disclosed by researcher Alex Birsan in February 2021, when he used the technique to breach over 35 major companies including Microsoft, Apple, PayPal, Netflix, and Tesla, earning over $130,000 in bug bounties. PortSwigger named it the top web hacking technique of 2021. In 2026, it is not just a researcher's trick anymore: Microsoft's threat intelligence team caught 33 malicious npm packages actively using dependency confusion to profile developer environments in May 2026, with explicit Sberbank financial sector targeting.

C'est la dependency confusion — divulguée pour la première fois par le chercheur Alex Birsan en février 2021, qui a utilisé la technique pour pénétrer dans plus de 35 grandes entreprises dont Microsoft, Apple, PayPal, Netflix et Tesla, gagnant plus de 130 000 $ en bug bounties. PortSwigger l'a nommée meilleure technique de hacking web de 2021. En 2026, ce n'est plus seulement un tour de chercheur : l'équipe de threat intelligence de Microsoft a découvert 33 packages npm malveillants utilisant activement la dependency confusion pour profiler les environnements de développeurs en mai 2026, avec un ciblage explicite du secteur financier Sberbank.

According to Orca Security research, 49% of organizations are currently vulnerable to dependency confusion attacks — and most don't know it. This guide explains exactly how the attack works in 2026, what the May 2026 Microsoft campaign looked like, and gives you a concrete step-by-step defense checklist that eliminates the attack surface entirely.

Selon les recherches d'Orca Security, 49% des organisations sont actuellement vulnérables aux attaques de dependency confusion — et la plupart ne le savent pas. Ce guide explique exactement comment fonctionne l'attaque en 2026, à quoi ressemblait la campagne Microsoft de mai 2026, et vous donne une liste de contrôle de défense concrète étape par étape qui élimine totalement la surface d'attaque.

49%
of organizations vulnerable to dependency confusion
des organisations vulnérables à la dependency confusion
Source: Orca Security Cloud Platform Research
35+
major companies breached by Birsan (2021) — Apple, Microsoft, PayPal, Netflix
grandes entreprises compromises par Birsan (2021) — Apple, Microsoft, PayPal, Netflix
Source: Alex Birsan / Medium, PortSwigger Top 10
33
malicious npm packages caught by Microsoft in May 2026
packages npm malveillants détectés par Microsoft en mai 2026
Source: Microsoft Security Blog, May 29, 2026
73%
rise in malicious open source packages in 2026
hausse des packages open source malveillants en 2026
Source: ReversingLabs 2026 Software Supply Chain Security Report

How Dependency Confusion Works: The npm Resolution Algorithm

Comment Fonctionne la Dependency Confusion : L’Algorithme de Résolution npm

npm resolves packages by checking registries in order. When your project has both a private registry (for internal packages) and falls back to the public registry (npmjs.com), it must decide which one wins for any given package name. The default behavior, without explicit per-scope registry pinning, is to prefer the highest version number across all configured registries.

npm résout les packages en vérifiant les registries dans l'ordre. Quand votre projet dispose à la fois d'un registry privé (pour les packages internes) et d'un fallback vers le registry public (npmjs.com), il doit décider lequel gagne pour un nom de package donné. Le comportement par défaut, sans épinglage de registry explicite par scope, est de préférer le numéro de version le plus élevé parmi tous les registries configurés.

This is the attack surface. If your internal package my-auth-utils is at version 1.2.3 in your private registry, and an attacker publishes a malicious my-auth-utils@9.0.0 on the public registry, npm will download the public version — because 9.0.0 > 1.2.3. The attacker doesn't need credentials. They just need to know the name of your private package.

C'est la surface d'attaque. Si votre package interne my-auth-utils est en version 1.2.3 dans votre registry privé, et qu'un attaquant publie un my-auth-utils@9.0.0 malveillant sur le registry public, npm téléchargera la version publique — car 9.0.0 > 1.2.3. L'attaquant n'a pas besoin de credentials. Il lui suffit de connaître le nom de votre package privé.

How does an attacker discover your private package names? Several ways:

Comment un attaquant découvre-t-il les noms de vos packages privés ? Plusieurs méthodes :

Once an attacker has a list of internal package names, the attack is trivial to execute: create an npm account, publish packages with those names at inflated version numbers, and add a malicious postinstall script. That script runs automatically on every npm install — no user interaction required.

Une fois qu'un attaquant dispose d'une liste de noms de packages internes, l'attaque est triviale à exécuter : créer un compte npm, publier des packages avec ces noms à des numéros de version gonflés, et ajouter un script postinstall malveillant. Ce script s'exécute automatiquement à chaque npm install — sans interaction utilisateur requise.

// package.json of the malicious public package
{
  "name": "my-auth-utils",
  "version": "100.100.100",
  "description": "Internal auth utilities",
  "scripts": {
    "postinstall": "node ./lib/collect.js"
  }
}

Note the version: 100.100.100. This is a version inflation tactic documented in the May 2026 Microsoft campaign. The inflated version ensures the public malicious package always wins the semver resolution race against any realistic internal version number. It also creates an unambiguous signal to security researchers — no legitimate package version looks like this — but most developers don't check.

Notez la version : 100.100.100. C'est une tactique d'inflation de version documentée dans la campagne Microsoft de mai 2026. La version gonflée garantit que le package public malveillant gagne toujours la course de résolution semver contre n'importe quel numéro de version interne réaliste. Cela crée également un signal non ambigu pour les chercheurs en sécurité — aucune version de package légitime ne ressemble à ça — mais la plupart des développeurs ne vérifient pas.

The May 2026 Microsoft Campaign: 33 Packages Profiling Windows Dev Environments

La Campagne Microsoft de Mai 2026 : 33 Packages Profilant les Environnements Windows

On May 28–29, 2026, Microsoft's threat intelligence team identified a coordinated dependency confusion campaign targeting organizational npm scopes. Three maintainer aliases published 33 malicious packages across two publication bursts, exploiting naming collisions across at least nine organizational scopes.

Les 28-29 mai 2026, l'équipe de threat intelligence de Microsoft a identifié une campagne de dependency confusion coordonnée ciblant les scopes npm organisationnels. Trois alias de mainteneurs ont publié 33 packages malveillants en deux rafales de publication, exploitant des collisions de noms dans au moins neuf scopes organisationnels.

The packages were designed to look like legitimate internal auth and UI modules. Names like @capibar.chat/ui-kit mimicked internal UI kit patterns. Most notably, @sber-ecom-core/sberpay-widget directly impersonated Sberbank's internal SberPay payment widget — making the campaign's financial-sector targeting explicit.

Les packages étaient conçus pour ressembler à des modules d'auth et d'UI internes légitimes. Des noms comme @capibar.chat/ui-kit imitaient les patterns de kits UI internes. Plus remarquablement, @sber-ecom-core/sberpay-widget usurpait directement le widget de paiement SberPay interne de Sberbank — rendant le ciblage financier de la campagne explicite.

The postinstall hook in each package executed an obfuscated reconnaissance payload that collected from any Windows machine that inadvertently pulled the package:

Le hook postinstall de chaque package exécutait un payload de reconnaissance obfusqué qui collectait depuis toute machine Windows ayant téléchargé par inadvertance le package :

This profile — hostname, username, dev stack — is the foundation for targeted spear-phishing and follow-on intrusion. The attack did not require executing persistent malware. Reconnaissance alone is sufficient to map an organization's development infrastructure and identify high-value targets within it.

Ce profil — nom d'hôte, utilisateur, stack de dev — est le fondement du spear-phishing ciblé et des intrusions ultérieures. L'attaque ne nécessitait pas d'exécuter de malware persistant. La reconnaissance seule suffit pour cartographier l'infrastructure de développement d'une organisation et identifier les cibles à haute valeur ajoutée.

Microsoft removed all known packages and revoked the associated publishing tokens within hours. But the campaign window had been active on the public registry — meaning any developer who ran npm install during that window with a vulnerable configuration may have unknowingly executed the payload.

Microsoft a supprimé tous les packages connus et révoqué les tokens de publication associés en quelques heures. Mais la fenêtre de la campagne avait été active sur le registry public — ce qui signifie que tout développeur ayant lancé npm install durant cette fenêtre avec une configuration vulnérable a pu exécuter le payload sans le savoir.

Other 2026 Dependency Confusion Campaigns: Genoma UI & Pattern Evolution

Autres Campagnes de Dependency Confusion en 2026 : Genoma UI & Évolution des Patterns

The Microsoft campaign was not an isolated event. SafeDep Security identified the "Genoma UI" dependency confusion campaign in 2026, targeting packages named after internal component library conventions common in enterprise frontend teams. The pattern is consistent: attackers scan public JavaScript bundles, public GitHub repos, and job postings for internal package name patterns, then register those names publicly.

La campagne Microsoft n'était pas un événement isolé. SafeDep Security a identifié la campagne de dependency confusion "Genoma UI" en 2026, ciblant des packages nommés d'après des conventions de bibliothèques de composants internes courantes dans les équipes frontend d'entreprise. Le schéma est cohérent : les attaquants scannent les bundles JavaScript publics, les dépôts GitHub publics et les offres d'emploi pour trouver des patterns de noms de packages internes, puis enregistrent ces noms publiquement.

ReversingLabs' 2026 Software Supply Chain Security Report documents a 73% rise in malicious open source packages year-over-year, with dependency confusion explicitly listed alongside typosquatting and GitHub Action manipulation as the top three technique families. The technique has industrialized since Birsan's 2021 disclosure: attackers now use automated tooling to scan millions of domains for internal package name leaks.

Le rapport 2026 de ReversingLabs sur la sécurité de la chaîne d'approvisionnement logicielle documente une hausse de 73% des packages open source malveillants d'une année sur l'autre, avec la dependency confusion explicitement répertoriée aux côtés du typosquatting et de la manipulation de GitHub Actions comme les trois principales familles de techniques. La technique s'est industrialisée depuis la divulgation de Birsan en 2021 : les attaquants utilisent désormais des outils automatisés pour analyser des millions de domaines à la recherche de fuites de noms de packages internes.

What makes 2026 different is the target profile. Early campaigns (2021–2023) went after enterprise internal package names broadly. 2026 campaigns show sector-specific intelligence gathering: the Sberbank targeting in the May Microsoft campaign, the Genoma UI campaign's frontend-team specificity, and the use of credential-themed package names that blend with typical auth library naming conventions.

Ce qui différencie 2026, c'est le profil des cibles. Les premières campagnes (2021-2023) visaient largement les noms de packages internes d'entreprise. Les campagnes de 2026 montrent une collecte de renseignements spécifique à des secteurs : le ciblage Sberbank dans la campagne Microsoft de mai, la spécificité des équipes frontend de la campagne Genoma UI, et l'utilisation de noms de packages à thème credential qui se fondent dans les conventions de nommage typiques des bibliothèques d'auth.

Version Inflation: Why 100.100.100 Beats Your Internal Version Every Time

L’Inflation de Version : Pourquoi 100.100.100 Bat Toujours Votre Version Interne

The technical mechanism deserves a closer look. npm uses semver (Semantic Versioning) to resolve which version of a package to install. When multiple registries are configured without scope-based pinning, npm queries all of them and picks the highest version. Attackers exploit this by publishing at absurdly high version numbers like 100.100.100, 9999.0.0, or 1337.1337.1337.

Le mécanisme technique mérite un examen plus approfondi. npm utilise semver (Semantic Versioning) pour résoudre quelle version d'un package installer. Lorsque plusieurs registries sont configurés sans épinglage basé sur les scopes, npm les interroge tous et choisit la version la plus élevée. Les attaquants exploitent cela en publiant à des numéros de version absurdement élevés comme 100.100.100, 9999.0.0, ou 1337.1337.1337.

# Your private registry has:
# @company/payments-sdk@2.4.1

# Attacker publishes to public npm:
# @company/payments-sdk@9999.0.0  (or 100.100.100, etc.)

# Without proper .npmrc scope pinning, npm ci may pick:
# "found: 9999.0.0 on registry.npmjs.org — installing..."

There is a secondary tactic: some campaigns mix realistic-looking versions with inflated ones. A package may publish 2.4.2 and 2.4.3 alongside 100.0.0. The realistic versions slip past automated detection filters that flag obviously inflated numbers, while still winning the version race against 2.4.1 from the private registry.

Il existe une tactique secondaire : certaines campagnes mélangent des versions à l'apparence réaliste avec des versions gonflées. Un package peut publier 2.4.2 et 2.4.3 aux côtés de 100.0.0. Les versions réalistes passent à travers les filtres de détection automatisés qui signalent les numéros manifestement gonflés, tout en gagnant quand même la course de version contre 2.4.1 du registry privé.

The combination of version inflation and a postinstall hook means the attack is zero-interaction. No one needs to explicitly import the malicious package — it just needs to appear in the resolved dependency tree. A developer running npm install to update an unrelated dependency could inadvertently trigger the payload.

La combinaison de l'inflation de version et d'un hook postinstall signifie que l'attaque est zéro-interaction. Personne n'a besoin d'importer explicitement le package malveillant — il doit juste apparaître dans l'arbre de dépendances résolu. Un développeur lançant npm install pour mettre à jour une dépendance sans rapport pourrait déclencher par inadvertance le payload.

Complete Defense Guide: Eliminating Dependency Confusion from Your npm Setup

Guide de Défense Complet : Éliminer la Dependency Confusion de Votre Configuration npm

Dependency confusion is one of the few supply chain attack vectors that can be completely eliminated with proper configuration. Unlike zero-days, there are no unknown unknowns here — the attack surface is fully understood and the mitigations are definitive.

La dependency confusion est l'un des rares vecteurs d'attaque de supply chain qui peut être complètement éliminé avec une configuration appropriée. Contrairement aux zero-days, il n'y a pas d'inconnues ici — la surface d'attaque est entièrement comprise et les mesures d'atténuation sont définitives.

1. Use Scoped Packages — The Most Effective Mitigation

1. Utiliser des Packages Scopés — La Mitigation la Plus Efficace

Rename all internal packages to use a private organizational scope: @mycompany/package-name. Scoped package names on npmjs.com require explicit organization ownership — an attacker cannot publish to @mycompany/* unless they control the @mycompany organization on npm. This makes dependency confusion attacks against properly scoped packages structurally impossible.

Renommez tous les packages internes pour utiliser un scope organisationnel privé : @mycompany/package-name. Les noms de packages scopés sur npmjs.com nécessitent une propriété organisationnelle explicite — un attaquant ne peut pas publier dans @mycompany/* à moins de contrôler l'organisation @mycompany sur npm. Cela rend les attaques de dependency confusion contre des packages correctement scopés structurellement impossibles.

// Before: unscoped internal package (vulnerable)
{ "dependencies": { "auth-utils": "^1.2.3" } }

// After: scoped package (safe)
{ "dependencies": { "@mycompany/auth-utils": "^1.2.3" } }

Important: Claim your organization scope on npmjs.com even if you do not publish any packages publicly. An unclaimed scope can be registered by anyone.

Important : Revendiquez votre scope organisationnel sur npmjs.com même si vous ne publiez aucun package publiquement. Un scope non revendiqué peut être enregistré par n'importe qui.

2. Pin Each Scope to Its Registry in .npmrc

2. Épingler Chaque Scope sur Son Registry dans .npmrc

The second critical control is .npmrc registry scope pinning. Configure your project's .npmrc to explicitly route each scope to the correct registry. Internal scopes must point to your private registry and never fall back to the public one:

Le second contrôle critique est l'épinglage de scope de registry dans .npmrc. Configurez le .npmrc de votre projet pour router explicitement chaque scope vers le bon registry. Les scopes internes doivent pointer vers votre registry privé et ne jamais tomber en fallback vers le public :

# .npmrc — commit this to every project repo
registry=https://registry.npmjs.org/

# Internal scope: ONLY resolve from private registry — no fallback
@mycompany:registry=https://registry.mycompany.com/
@mycompany:always-auth=true

# Block public fallback for internal scope
@mycompany:strict-ssl=true

For Verdaccio (self-hosted registry), additionally configure the registry to block proxying public packages for your internal scopes:

Pour Verdaccio (registry auto-hébergé), configurez également le registry pour bloquer le proxying des packages publics pour vos scopes internes :

# verdaccio/config.yaml
packages:
  '@mycompany/*':
    access: $authenticated
    publish: $authenticated
    # NO proxy: do not fall back to public registry for internal scope
  '**':
    access: $all
    publish: $authenticated
    proxy: npmjs  # public packages still proxied normally

3. Register Your Internal Package Names on npmjs.com

3. Enregistrer Vos Noms de Packages Internes sur npmjs.com

For unscoped packages that cannot be renamed immediately, claim their names on the public registry. Publish empty placeholder packages with a private: true flag and a clear README explaining the package is reserved for internal use. This prevents an attacker from registering them:

Pour les packages non scopés qui ne peuvent pas être renommés immédiatement, revendiquez leurs noms sur le registry public. Publiez des packages placeholder vides avec un flag private: true et un README clair expliquant que le package est réservé à usage interne. Cela empêche un attaquant de les enregistrer :

// placeholder package.json published to public npm
{
  "name": "auth-utils",
  "version": "0.0.1",
  "description": "Reserved — internal package. Do not install.",
  "private": false,
  "main": "index.js"
}

4. Configure Dependabot for Private Registry Authentication

4. Configurer Dependabot pour l’Authentification au Registry Privé

If you use Dependabot for automated dependency updates, configure it to authenticate against your private registry for internal scopes. Without this, Dependabot will only check the public registry for updates — and could inadvertently trigger confusion if your configuration allows public fallback:

Si vous utilisez Dependabot pour les mises à jour automatiques de dépendances, configurez-le pour s'authentifier auprès de votre registry privé pour les scopes internes. Sans ça, Dependabot ne vérifiera que le registry public pour les mises à jour — et pourrait déclencher par inadvertance une confusion si votre configuration permet le fallback public :

# .github/dependabot.yml
version: 2
registries:
  mycompany-npm:
    type: npm-registry
    url: https://registry.mycompany.com/
    token: ${{ secrets.MYCOMPANY_NPM_TOKEN }}
updates:
  - package-ecosystem: npm
    directory: /
    schedule:
      interval: weekly
    registries:
      - mycompany-npm

5. Disable postinstall Scripts in CI/CD

5. Désactiver les Scripts postinstall en CI/CD

Add --ignore-scripts to your CI/CD npm ci invocations. This flag prevents postinstall hooks from executing during install — blocking the payload execution even if a dependency confusion package somehow slips through:

Ajoutez --ignore-scripts à vos invocations npm ci en CI/CD. Ce flag empêche l'exécution des hooks postinstall lors de l'installation — bloquant l'exécution du payload même si un package de confusion de dépendances passe d'une façon ou d'une autre :

# GitHub Actions — safe npm install
- name: Install dependencies
  run: npm ci --ignore-scripts --audit
  env:
    NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Note: --ignore-scripts alone is not a complete defense — Phantom Gyp (the Miasma technique) bypasses it via binding.gyp. It should be used alongside the scope pinning and registry configuration above, not instead of them.

Note : --ignore-scripts seul n'est pas une défense complète — Phantom Gyp (la technique Miasma) le contourne via binding.gyp. Il doit être utilisé en complément de l'épinglage de scope et de la configuration du registry ci-dessus, pas à leur place.

6. Monitor for New Public Registrations of Your Internal Package Names

6. Surveiller les Nouvelles Inscriptions Publiques de Vos Noms de Packages Internes

Set up automated monitoring to alert you if any of your internal package names appear on the public npm registry. The npm vulnerability monitoring in OptiBot tracks your entire dependency graph — including package name conflicts. You can also use the npm registry API to poll for new registrations:

Mettez en place une surveillance automatisée pour vous alerter si l'un de vos noms de packages internes apparaît sur le registry npm public. La surveillance des vulnérabilités npm dans OptiBot trace l'ensemble de votre graphe de dépendances — y compris les conflits de noms de packages. Vous pouvez également utiliser l'API du registry npm pour surveiller les nouvelles inscriptions :

# Check if an internal package name has been claimed on public npm
# Returns 404 if safe, 200 if someone has registered it
curl -s -o /dev/null -w "%{http_code}" \
  https://registry.npmjs.org/my-internal-package-name
# If 200: claim it immediately or rename to scoped package

Dependency Confusion Defense Checklist

Checklist de Défense Contre la Dependency Confusion

Must Do
Obligatoire
All internal packages use @org/name scoping
Tous les packages internes utilisent le scope @org/name
Must Do
Obligatoire
@org:registry=https://private.registry/ pinned in .npmrc, committed to repo
@org:registry=https://private.registry/ épinglé dans .npmrc, versionné dans le repo
Must Do
Obligatoire
Organization scope claimed on npmjs.com (even if no public packages)
Scope organisationnel revendiqué sur npmjs.com (même sans packages publics)
Must Do
Obligatoire
Private registry configured to not proxy public packages for internal scope (Verdaccio: no proxy for @org/*)
Registry privé configuré pour ne pas proxifier les packages publics pour le scope interne (Verdaccio : pas de proxy pour @org/*)
Recommended
Recommandé
npm ci --ignore-scripts in CI/CD pipelines
npm ci --ignore-scripts dans les pipelines CI/CD
Recommended
Recommandé
Placeholder packages registered on public npm for any unscoped internal names
Packages placeholder enregistrés sur npm public pour tout nom interne non scopé
Recommended
Recommandé
Dependabot configured with private registry credentials for internal scopes
Dependabot configuré avec les credentials du registry privé pour les scopes internes
Monitor
Surveiller
Automated alerts if internal package names appear on public npm (poll registry API or use OptiBot)
Alertes automatisées si des noms de packages internes apparaissent sur npm public (polling API registry ou OptiBot)

Frequently Asked Questions

Questions fréquentes

Is dependency confusion the same as typosquatting?

La dependency confusion est-elle la même chose que le typosquatting ?

No. Typosquatting targets developers who mistype a public package name (e.g., reacct instead of react). Dependency confusion uses the exact correct name of a private internal package and exploits the registry resolution algorithm to deliver the malicious version automatically — without any user error required. Dependency confusion is generally considered more dangerous because it is fully automated and invisible.

Non. Le typosquatting cible les développeurs qui font une faute de frappe dans un nom de package public (par ex. reacct au lieu de react). La dependency confusion utilise le nom exact et correct d'un package interne privé et exploite l'algorithme de résolution du registry pour livrer automatiquement la version malveillante — sans aucune erreur de l'utilisateur requise. La dependency confusion est généralement considérée comme plus dangereuse car elle est entièrement automatisée et invisible.

Does using npm ci instead of npm install protect against dependency confusion?

Utiliser npm ci plutôt que npm install protège-t-il contre la dependency confusion ?

npm ci installs from the lockfile and fails if the lockfile is out of sync — which is better for reproducibility. However, npm ci does not prevent dependency confusion. If the lockfile was generated on a vulnerable machine (without proper scope pinning), it may already contain the malicious package's resolved URL and integrity hash. npm ci would then faithfully install the malicious version. Scope pinning in .npmrc is the correct defense.

npm ci installe depuis le lockfile et échoue si le lockfile est désynchronisé — ce qui est mieux pour la reproductibilité. Cependant, npm ci ne prévient pas la dependency confusion. Si le lockfile a été généré sur une machine vulnérable (sans épinglage de scope approprié), il peut déjà contenir l'URL résolue et le hash d'intégrité du package malveillant. npm ci installerait alors fidèlement la version malveillante. L'épinglage de scope dans .npmrc est la bonne défense.

We only use public packages — are we vulnerable?

Nous n’utilisons que des packages publics — sommes-nous vulnérables ?

If all your dependencies are public npm packages with no private registry involved, dependency confusion does not apply to you. The attack specifically targets the gap between private and public registries. However, if you ever set up a private registry in the future (for internal tools, white-labelled packages, or organizational monorepos), the risk becomes active immediately.

Si toutes vos dépendances sont des packages npm publics sans registry privé impliqué, la dependency confusion ne vous concerne pas. L'attaque cible spécifiquement l'écart entre les registries privés et publics. Cependant, si vous mettez un jour un registry privé en place (pour des outils internes, des packages en marque blanche, ou des monorepos organisationnels), le risque devient actif immédiatement.

What if we use a private registry that proxies public packages — like Verdaccio in default mode?

Et si nous utilisons un registry privé qui proxifie les packages publics — comme Verdaccio en mode par défaut ?

Proxying public packages through your private registry is not sufficient protection on its own. Verdaccio's default configuration proxies all packages from the public registry, including ones an attacker has registered. The key mitigation is to configure your private registry to never proxy the public registry for your internal scope (@mycompany/*) — so if a package named @mycompany/foo does not exist in your private registry, the install fails rather than falling back to public npm.

Proxifier les packages publics via votre registry privé n'est pas une protection suffisante en soi. La configuration par défaut de Verdaccio proxifie tous les packages du registry public, y compris ceux qu'un attaquant a enregistrés. La mitigation clé est de configurer votre registry privé pour ne jamais proxifier le registry public pour votre scope interne (@mycompany/*) — ainsi si un package nommé @mycompany/foo n'existe pas dans votre registry privé, l'installation échoue plutôt que de tomber en fallback vers npm public.

Can a SCA scanner detect dependency confusion packages?

Un scanner SCA peut-il détecter les packages de dependency confusion ?

Traditional SCA scanners (which match package versions against CVE databases) generally cannot detect dependency confusion attacks, because the confusion package itself is not a known vulnerability — it is a newly published package with no CVE assigned yet. Behavioral analysis tools (Socket.dev, Snyk's malicious package detection, OpenSSF Package Analysis) are better suited to catching dependency confusion packages by flagging postinstall scripts that collect and exfiltrate system information. Continuous monitoring of your dependency graph for unexpected version changes is a key detection signal.

Les scanners SCA traditionnels (qui comparent les versions de packages aux bases de données CVE) ne peuvent généralement pas détecter les attaques de dependency confusion, car le package de confusion lui-même n'est pas une vulnérabilité connue — c'est un package nouvellement publié sans CVE assigné. Les outils d'analyse comportementale (Socket.dev, détection de packages malveillants Snyk, OpenSSF Package Analysis) sont mieux adaptés pour détecter les packages de dependency confusion en signalant les scripts postinstall qui collectent et exfiltrent des informations système. La surveillance continue de votre graphe de dépendances pour détecter les changements de version inattendus est un signal de détection clé.

Does pnpm or Yarn have the same vulnerability?

pnpm ou Yarn ont-ils la même vulnérabilité ?

Yes — dependency confusion is a package manager pattern, not an npm-specific bug. pnpm and Yarn both support multiple registry configurations and can be misconfigured in the same way. The mitigations are analogous: use .npmrc (for pnpm, which reads it) or .yarnrc.yml (for Yarn Berry) to pin internal scopes to your private registry and disable public fallback for those scopes.

Oui — la dependency confusion est un pattern de gestionnaire de packages, pas un bug spécifique à npm. pnpm et Yarn supportent tous deux des configurations multi-registry et peuvent être mal configurés de la même façon. Les mesures d'atténuation sont analogues : utilisez .npmrc (pour pnpm, qui le lit) ou .yarnrc.yml (pour Yarn Berry) pour épingler les scopes internes vers votre registry privé et désactiver le fallback public pour ces scopes.

Detect Unexpected Package Version Changes Automatically

Détectez les Changements de Version de Packages Inattendus Automatiquement

Dependency confusion packages appear as unexpected version bumps in your lockfile. CVE OptiBot monitors your dependency graph continuously — alerting you when a package resolves from an unexpected source, a version number jumps unusually high, or a new public package appears with the same name as a dependency in your project.

Les packages de dependency confusion apparaissent comme des changements de version inattendus dans votre lockfile. CVE OptiBot surveille votre graphe de dépendances en continu — vous alertant quand un package se résout depuis une source inattendue, qu'un numéro de version monte inhabituellement haut, ou qu'un nouveau package public apparaît avec le même nom qu'une dépendance de votre projet.

Start free monitoring Démarrer le monitoring gratuit