On June 17, 2026, an attacker republished the entire @mastra npm scope — 143 packages — by exploiting a single stale contributor account. The foothold was ehindero, the npm account of a former Mastra contributor who had not been removed from the publishing team after leaving the project. Using those outdated credentials, the attacker slipped a malicious dependency into every @mastra package, including @mastra/core, which pulls approximately 4 million downloads a month. Hundreds of dependent projects were at risk for hours before npm revoked the account and pulled the malicious releases.
Le 17 juin 2026, un attaquant a republié l'intégralité du scope npm @mastra — 143 packages — en exploitant un seul compte contributeur obsolète. Le point d'entrée était ehindero, le compte npm d'un ancien contributeur de Mastra qui n'avait pas été retiré de l'équipe de publication après son départ. En utilisant ces credentials périmés, l'attaquant a glissé une dépendance malveillante dans chaque package @mastra, y compris @mastra/core qui comptabilise environ 4 millions de téléchargements par mois. Des centaines de projets dépendants ont été exposés pendant des heures avant que npm ne révoque le compte et retire les versions malveillantes.
This is the defining supply chain threat pattern of June 2026: not the sophisticated OIDC token hijack of the TanStack attack (May 11), not the Phantom Gyp binding.gyp bypass of Miasma (June 1–9), but the simplest possible credential attack — a forgotten account with publish rights. npm scoped packages were designed to be security boundaries. An @yourorg scope is supposed to mean something — that every package under it was published by your organization. When a stale maintainer account is not cleaned up, that boundary collapses silently.
C'est le pattern de menace supply chain caractéristique de juin 2026 : pas le détournement de token OIDC sophistiqué de l'attaque TanStack (11 mai), pas le bypass binding.gyp Phantom Gyp de Miasma (1–9 juin), mais l'attaque de credential la plus simple possible — un compte oublié avec des droits de publication. Les packages npm scoped étaient conçus pour être des frontières de sécurité. Un scope @votreorg est censé avoir une signification — que chaque package sous ce scope a été publié par votre organisation. Quand un compte mainteneur obsolète n'est pas nettoyé, cette frontière s'effondre silencieusement.
This guide covers everything you need to lock down npm scoped packages in 2026: how scope takeover attacks work, a complete comparison of private registry options (Verdaccio, GitHub Packages, Artifactory, Nexus), a hardening checklist for each, npm token security best practices (90-day caps, OIDC trusted publishing), and a CI/CD publishing guide that eliminates long-lived token exposure.
Ce guide couvre tout ce dont vous avez besoin pour sécuriser les packages npm scoped en 2026 : comment fonctionnent les attaques de prise de contrôle de scope, une comparaison complète des options de registry privé (Verdaccio, GitHub Packages, Artifactory, Nexus), une checklist de durcissement pour chacun, les meilleures pratiques de sécurité des tokens npm (plafond 90 jours, publication OIDC), et un guide de publication CI/CD qui élimine l'exposition aux tokens longue durée.
How npm Scopes Work — and Why They Are a Security Boundary
Comment Fonctionnent les Scopes npm — et Pourquoi ce Sont des Frontières de Sécurité
An npm scope is a namespace prefix for packages: @company/package-name. The public npm registry enforces that only members of the @company organization on npm can publish packages under that scope. This creates a trust model: if you see @angular/core, you can assume it was published by the Angular team. If you see @mastra/core, you should be able to assume it came from the Mastra project.
Un scope npm est un préfixe de namespace pour les packages : @company/package-name. Le registry npm public impose que seuls les membres de l'organisation @company sur npm peuvent publier des packages sous ce scope. Cela crée un modèle de confiance : si vous voyez @angular/core, vous pouvez supposer qu'il a été publié par l'équipe Angular. Si vous voyez @mastra/core, vous devriez pouvoir supposer qu'il vient du projet Mastra.
This model has three critical failure modes that 2026 attacks are actively exploiting:
Ce modèle a trois modes d'échec critiques que les attaques de 2026 exploitent activement :
- Stale maintainer accounts — former contributors who retain publish rights after leaving a project. The Mastra attack (June 17, 2026) and the AntV attack (May 19, 2026, via TeamPCP targeting a compromised maintainer) both exploited this vector.
- Comptes mainteneurs obsolètes — anciens contributeurs qui conservent des droits de publication après avoir quitté un projet. L'attaque Mastra (17 juin 2026) et l'attaque AntV (19 mai 2026, via TeamPCP ciblant un mainteneur compromis) ont toutes deux exploité ce vecteur.
- Compromised maintainer credentials — account takeover via phishing, credential stuffing, or stolen tokens. The Axios attack (March 2026) fell into this category: the lead maintainer's npm account was seized, and the attacker bypassed OIDC Trusted Publisher protections by manually publishing with the stolen token.
- Credentials mainteneur compromis — prise de contrôle du compte par phishing, credential stuffing ou tokens volés. L'attaque Axios (mars 2026) relevait de cette catégorie : le compte npm du mainteneur principal a été saisi, et l'attaquant a contourné les protections OIDC Trusted Publisher en publiant manuellement avec le token volé.
- CI/CD pipeline hijack — the attacker injects malicious code into the build pipeline itself, causing the legitimate publishing workflow to produce and sign malicious packages. This is what happened in the TanStack attack (May 11, 2026, CVE-2026-45321 CVSS 9.6): 84 malicious versions published under TanStack's own OIDC identity.
- Détournement de pipeline CI/CD — l'attaquant injecte du code malveillant dans le pipeline de build lui-même, faisant en sorte que le workflow de publication légitime produise et signe des packages malveillants. C'est ce qui s'est passé lors de l'attaque TanStack (11 mai 2026, CVE-2026-45321 CVSS 9,6) : 84 versions malveillantes publiées sous l'identité OIDC propre à TanStack.
The Mastra attack is particularly instructive because it required the least sophistication. No account compromise. No OIDC bypass. The attacker simply used credentials that the project had never revoked. This is the default state of virtually every open-source project that has had contributor turnover.
L'attaque Mastra est particulièrement instructive car elle a nécessité le moins de sophistication. Aucune compromission de compte. Aucun bypass OIDC. L'attaquant a simplement utilisé des credentials que le projet n'avait jamais révoqués. C'est l'état par défaut de pratiquement tout projet open-source qui a connu une rotation de contributeurs.
The June 2026 Scope Takeover Epidemic: @mastra, @redhat-cloud-services, @antv
L’Épidémie de Prise de Contrôle de Scope de Juin 2026 : @mastra, @redhat-cloud-services, @antv
Three major scope-level supply chain attacks have occurred in the last 30 days. Each targeted an entire organizational npm scope — not individual packages — and each had a different entry point:
Trois grandes attaques supply chain au niveau du scope ont eu lieu au cours des 30 derniers jours. Chacune ciblait l'intégralité d'un scope npm organisationnel — pas des packages individuels — et chacune avait un point d'entrée différent :
- @antv / TeamPCP (May 19, 2026): The Mini Shai-Hulud campaign attributed to TeamPCP compromised a maintainer account for the @antv data visualization ecosystem (used by Ant Design / Alibaba's design system). 300+ malicious versions published across 323 packages in a 22-minute automated burst. The worm then used the stolen npm token to spread to other packages maintained by the same developer.
- @antv / TeamPCP (19 mai 2026) : La campagne Mini Shai-Hulud attribuée à TeamPCP a compromis un compte mainteneur de l'écosystème de visualisation de données @antv (utilisé par Ant Design / le design system d'Alibaba). 300+ versions malveillantes publiées sur 323 packages en une rafale automatisée de 22 minutes. Le ver a ensuite utilisé le token npm volé pour se propager aux autres packages maintenus par le même développeur.
- @redhat-cloud-services / Miasma (June 1, 2026): 32 packages under Red Hat's official npm scope were backdoored via a compromised Red Hat employee GitHub account and GitHub Actions OIDC tokens. The attack leveraged Phantom Gyp — a 157-byte
binding.gypfile — to execute the payload even with--ignore-scriptsenabled. - @redhat-cloud-services / Miasma (1er juin 2026) : 32 packages du scope npm officiel de Red Hat ont été backdoorés via un compte GitHub d'employé Red Hat compromis et des tokens OIDC GitHub Actions. L'attaque a utilisé Phantom Gyp — un fichier
binding.gypde 157 octets — pour exécuter le payload même avec--ignore-scriptsactivé. - @mastra (June 17, 2026): A forgotten contributor account published malicious versions across all 143 packages in the @mastra scope. @mastra/core (~4M monthly downloads) was the highest-impact target. The attack vector required zero technical sophistication — just knowledge of an account that still had publish rights.
- @mastra (17 juin 2026) : Un compte contributeur oublié a publié des versions malveillantes sur les 143 packages du scope @mastra. @mastra/core (~4 millions de téléchargements/mois) était la cible à plus fort impact. Le vecteur d'attaque n'a requis aucune sophistication technique — juste la connaissance d'un compte qui avait encore des droits de publication.
The pattern is clear: npm scopes are organizational trust signals that are treated as configuration artifacts, not security assets. Contributors are added and forgotten. Tokens are issued and never rotated. Automation credentials outlive the projects they were created for. This is the 2026 supply chain threat surface.
Le pattern est clair : les scopes npm sont des signaux de confiance organisationnels qui sont traités comme des artefacts de configuration, pas comme des actifs de sécurité. Les contributeurs sont ajoutés et oubliés. Les tokens sont émis et jamais tournés. Les credentials d'automatisation survivent aux projets pour lesquels ils ont été créés. C'est la surface de menace supply chain de 2026.
Private npm Registry Options in 2026: Verdaccio vs GitHub Packages vs Artifactory vs Nexus
Options de Registry npm Privé en 2026 : Verdaccio vs GitHub Packages vs Artifactory vs Nexus
Running a private npm registry lets you host internal packages and cache public packages locally, eliminating dependency confusion attacks and improving install reliability. Here's a comparison of the four main options in 2026, with security as the primary lens:
Gérer un registry npm privé vous permet d'héberger des packages internes et de mettre en cache des packages publics localement, éliminant les attaques de dependency confusion et améliorant la fiabilité des installations. Voici une comparaison des quatre principales options en 2026, avec la sécurité comme prisme principal :
| Registry | Type | Cost (2026) | Key Security Features | |||
|---|---|---|---|---|---|---|
| Registry | Type | Coût (2026) | Fonctionnalités Sécurité Clés | |||
| Verdaccio | Open source, self-hosted | Open source, auto-hébergé | Free | Gratuit | HTTPS via proxy, JWT tokens, htpasswd/LDAP/GitLab auth, per-scope proxy control (proxy: []), rate limiting (v5.4.0+), verdaccio-security-filter plugin for CVE scanning |
HTTPS via proxy, tokens JWT, auth htpasswd/LDAP/GitLab, contrôle proxy par scope (proxy: []), rate limiting (v5.4.0+), plugin verdaccio-security-filter pour scan CVE |
| GitHub Packages | Hosted SaaS (GitHub) | SaaS hébergé (GitHub) | Free for public; from $4/user/mo for private | Gratuit pour le public ; à partir de 4 $/user/mois pour le privé | GITHUB_TOKEN (short-lived, job-scoped), granular PAT permissions, audit log API, fine-grained org access control, native GitHub Actions OIDC integration | GITHUB_TOKEN (courte durée, scopé par job), permissions PAT granulaires, API audit log, contrôle d’accès org granulaire, intégration OIDC GitHub Actions native |
| JFrog Artifactory | Enterprise (SaaS or self-hosted) | Entreprise (SaaS ou auto-hébergé) | From ~$150/month; scales with consumption | À partir de ~150 $/mois ; évolue selon la consommation | 20+ package formats, Xray CVE scanning (bundled), role-based access, immutable artifact repositories, SCIM provisioning, SOC2/FIPS compliance | 20+ formats de packages, scan CVE Xray (inclus), accès basé sur les rôles, dépôts d'artefacts immuables, provisionnement SCIM, conformité SOC2/FIPS |
| Sonatype Nexus | Enterprise (SaaS or self-hosted) | Entreprise (SaaS ou auto-hébergé) | From ~$120/month | À partir de ~120 $/mois | OWASP Dependency-Check integration, IQ Server for policy enforcement, malware detection, quarantine mode for flagged packages, audit trails | Intégration OWASP Dependency-Check, IQ Server pour l'application de politiques, détection de malwares, mode quarantaine pour les packages signalés, pistes d'audit |
Which to choose? Verdaccio is the right choice for small teams (under 20 engineers), air-gapped environments, and teams that need full control without vendor lock-in. GitHub Packages is the easiest if your team already lives in GitHub — GITHUB_TOKEN eliminates long-lived credentials entirely for Actions workflows. Artifactory and Nexus are enterprise plays with compliance requirements (SOC2, FIPS), built-in CVE scanning, and multi-format support (npm, Maven, PyPI, Docker in one system).
Lequel choisir ? Verdaccio est le bon choix pour les petites équipes (moins de 20 ingénieurs), les environnements air-gapped et les équipes qui ont besoin d'un contrôle total sans dépendance fournisseur. GitHub Packages est le plus simple si votre équipe vit déjà dans GitHub — GITHUB_TOKEN élimine entièrement les credentials longue durée pour les workflows Actions. Artifactory et Nexus sont des solutions entreprise avec des exigences de conformité (SOC2, FIPS), un scan CVE intégré et un support multi-format (npm, Maven, PyPI, Docker dans un seul système).
Verdaccio Security Hardening: The Complete 2026 Configuration Guide
Durcissement de Sécurité Verdaccio : Le Guide de Configuration Complet 2026
If you run Verdaccio, the default configuration leaves several critical security gaps open. Here is the hardened configuration that closes them:
Si vous gérez Verdaccio, la configuration par défaut laisse plusieurs lacunes de sécurité critiques ouvertes. Voici la configuration durcie qui les comble :
# /etc/verdaccio/config.yaml — Hardened Verdaccio 2026
# 1. HTTPS: run behind a reverse proxy (nginx/Caddy) with TLS
# Never expose Verdaccio directly on port 80
listen: 127.0.0.1:4873
# 2. Storage: local storage with regular backup to S3/GCS
storage: /var/data/verdaccio/storage
# 3. Authentication: use JWT + LDAP or GitLab for SSO
auth:
htpasswd:
file: /etc/verdaccio/htpasswd
max_users: 100
algorithm: bcrypt
# 4. JWT tokens: better performance, configurable expiry
security:
api:
jwt:
sign:
expiresIn: 15d # 15 days max for dev tokens
web:
sign:
expiresIn: 7d
# 5. Package access control: require auth for everything
packages:
# Internal scoped packages: NEVER proxy to public registry
"@yourcompany/*":
access: $authenticated
publish: $authenticated
proxy: [] # Critical: blocks dependency confusion attacks
# Trusted public scopes: cache but don't allow publishing
"@types/*":
access: $all
publish: $nobody
proxy: npmjs
# All other packages: proxy through to public registry
"**":
access: $all
publish: $authenticated
proxy: npmjs
# 6. Uplinks: define public registry as upstream
uplinks:
npmjs:
url: https://registry.npmjs.org/
timeout: 30s
maxage: 10m
# Verify package integrity from upstream
strict_ssl: true
# 7. Rate limiting (built-in since v5.4.0)
server:
keepAliveTimeout: 60
# Rate limiting for auth endpoints prevents brute-force
rateLimit:
windowMs: 900000 # 15 minutes
max: 100
# 8. Audit log: track all publish/access events
log:
type: file
path: /var/log/verdaccio/verdaccio.log
format: json
level: http
The most important line is proxy: [] on your internal scope. Without it, Verdaccio will fall back to the public registry for any @yourcompany/* package it does not have locally — which is exactly how dependency confusion attacks work. With proxy: [], if a package doesn't exist in your local registry, the install fails loudly instead of silently pulling an attacker's version from npmjs.com.
La ligne la plus importante est proxy: [] sur votre scope interne. Sans elle, Verdaccio se rabattra sur le registry public pour tout package @votrecompany/* qu'il n'a pas localement — ce qui est exactement ainsi que fonctionnent les attaques de dependency confusion. Avec proxy: [], si un package n'existe pas dans votre registry local, l'installation échoue bruyamment plutôt que de télécharger silencieusement la version d'un attaquant depuis npmjs.com.
For additional defense, the verdaccio-security-filter plugin adds CVE scanning against multiple vulnerability databases, package allowlist/blocklist enforcement, and license compliance checks — blocking malicious packages before they enter your cache.
Pour une défense supplémentaire, le plugin verdaccio-security-filter ajoute le scan CVE contre plusieurs bases de données de vulnérabilités, l'application de listes d'autorisation/blocage de packages, et les vérifications de conformité des licences — bloquant les packages malveillants avant qu'ils entrent dans votre cache.
npm Token Security in 2026: 90-Day Caps, Granular Permissions & OIDC Trusted Publishing
Sécurité des Tokens npm en 2026 : Plafond 90 Jours, Permissions Granulaires & Publication OIDC
The Mastra attack was enabled by a token that had never been rotated. The npm ecosystem has historically been reckless with token lifetimes — classic tokens were permanent by default, and many projects still have publishing tokens from 2019 sitting in CI/CD environment variables. npm (GitHub) has been tightening token security since late 2025, and the 2026 changes are significant:
L'attaque Mastra a été rendue possible par un token qui n'avait jamais été tourné. L'écosystème npm a historiquement été négligent avec les durées de vie des tokens — les tokens classiques étaient permanents par défaut, et de nombreux projets ont encore des tokens de publication de 2019 dans des variables d'environnement CI/CD. npm (GitHub) a renforcé la sécurité des tokens depuis fin 2025, et les changements de 2026 sont significatifs :
- Classic token creation disabled (November 5, 2025): npm has disabled the creation of classic (permanent) tokens. All new tokens must be granular tokens with explicit expiry.
- Création de tokens classiques désactivée (5 novembre 2025) : npm a désactivé la création de tokens classiques (permanents). Tous les nouveaux tokens doivent être des tokens granulaires avec expiration explicite.
- 90-day maximum for write tokens: All granular tokens with write permissions are now capped at 90 days maximum lifetime. Existing tokens with longer lifetimes were automatically expired on February 3, 2026.
- Maximum de 90 jours pour les tokens d'écriture : Tous les tokens granulaires avec permissions d'écriture sont désormais plafonnés à 90 jours de durée de vie maximum. Les tokens existants avec des durées de vie plus longues ont été automatiquement expirés le 3 février 2026.
- 2FA required for new write tokens: New npm tokens with write permissions now enforce two-factor authentication by default, with a dedicated "Bypass 2FA" option for CI/CD (unchecked by default).
- 2FA requis pour les nouveaux tokens d'écriture : Les nouveaux tokens npm avec permissions d'écriture imposent désormais l'authentification à deux facteurs par défaut, avec une option dédiée "Bypass 2FA" pour CI/CD (décochée par défaut).
Even with these improvements, a 90-day token window is still long enough for damage. The recommended approach is to eliminate long-lived publishing tokens entirely by using OIDC Trusted Publishing:
Même avec ces améliorations, une fenêtre de token de 90 jours est encore suffisamment longue pour causer des dégâts. L'approche recommandée est d'éliminer entièrement les tokens de publication longue durée en utilisant la Publication de Confiance OIDC :
# .github/workflows/publish.yml — OIDC Trusted Publishing
# No npm token stored anywhere — credentials are job-scoped and ephemeral
name: Publish to npm
on:
push:
tags:
- 'v*'
permissions:
contents: read
id-token: write # Required for OIDC token generation
jobs:
publish:
runs-on: ubuntu-latest
environment: npm-publish # Gate behind a protected environment
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
# OIDC trusted publish: npm generates a short-lived token
# scoped to this exact job, this exact workflow, this exact repo
- name: Publish to npm
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# With OIDC configured on npm.js, NODE_AUTH_TOKEN is not needed
# The --provenance flag generates a Sigstore attestation
To configure OIDC Trusted Publishing on npmjs.com: go to your npm account settings → Granular Access Tokens → "Trusted Publishing" tab. Add your GitHub repository and workflow file path. Once configured, the npm publish command will automatically obtain a short-lived, job-scoped credential from npm without any stored token. Trusted publishing is supported for GitHub Actions and GitLab CI/CD, with Azure Pipelines and CircleCI support in active development.
Pour configurer la Publication de Confiance OIDC sur npmjs.com : allez dans les paramètres de votre compte npm → Tokens d'accès granulaires → onglet "Trusted Publishing". Ajoutez votre dépôt GitHub et le chemin du fichier workflow. Une fois configuré, la commande npm publish obtient automatiquement un credential de courte durée, scoped au job, depuis npm sans aucun token stocké. La publication de confiance est supportée pour GitHub Actions et GitLab CI/CD, avec un support Azure Pipelines et CircleCI en développement actif.
Maintainer Access Hygiene: The Stale Account Audit Checklist
Hygiène des Accès Mainteneur : La Checklist d’Audit des Comptes Obsolètes
The Mastra attack would not have succeeded if the project had a routine maintainer offboarding process. This is the most underrated supply chain risk in 2026: not sophisticated zero-days, but forgotten accounts with publish rights. Here is the full remediation checklist:
L'attaque Mastra n'aurait pas réussi si le projet avait eu un processus routinier d'offboarding des mainteneurs. C'est le risque supply chain le plus sous-estimé en 2026 : pas des zero-days sophistiqués, mais des comptes oubliés avec des droits de publication. Voici la checklist de remédiation complète :
- Audit all current maintainers:
npm owner ls <package-name>lists all owners for a package. For organizations with many packages, this must be scripted. - Auditer tous les mainteneurs actuels :
npm owner ls <nom-du-package>liste tous les propriétaires d'un package. Pour les organisations avec de nombreux packages, cela doit être scripté. - Remove stale accounts immediately:
npm owner rm <username> <package-name>. For GitHub-managed scopes, revoke access via the npm organization settings page. - Supprimer immédiatement les comptes obsolètes :
npm owner rm <username> <nom-du-package>. Pour les scopes gérés par GitHub, révoquer l'accès via la page des paramètres de l'organisation npm. - Require 2FA for all maintainers: In npm organization settings, enable "Require two-factor authentication". Any account without 2FA will be blocked from publishing.
- Exiger la 2FA pour tous les mainteneurs : Dans les paramètres de l'organisation npm, activez "Require two-factor authentication". Tout compte sans 2FA sera bloqué de la publication.
- Audit all publishing tokens: In npm account settings → Access Tokens, review and revoke any token that is not associated with a current, active workflow. Check expiry dates — any token approaching 90 days should be rotated now.
- Auditer tous les tokens de publication : Dans les paramètres du compte npm → Tokens d'accès, passez en revue et révoquez tout token qui n'est pas associé à un workflow actif actuel. Vérifiez les dates d'expiration — tout token approchant 90 jours doit être tourné maintenant.
- Migrate CI/CD to OIDC Trusted Publishing: Replace any stored npm token in CI/CD environment variables with OIDC trusted publishing. This eliminates the token theft attack vector entirely for automated publishing.
- Migrer CI/CD vers la Publication de Confiance OIDC : Remplacez tout token npm stocké dans des variables d'environnement CI/CD par la publication de confiance OIDC. Cela élimine entièrement le vecteur de vol de token pour la publication automatisée.
- Add
publish --provenanceto all release workflows: Provenance attestations link each published version to its exact build environment, source commit, and CI workflow. While SLSA Build Level 2 (not L3) provenance can be forged by a hijacked pipeline, it still provides a verifiable audit trail that was absent in the Mastra and AntV attacks. - Ajouter
publish --provenanceà tous les workflows de release : Les attestations de provenance lient chaque version publiée à son environnement de build exact, son commit source et son workflow CI. Bien que la provenance SLSA Build Level 2 (pas L3) puisse être falsifiée par un pipeline détourné, elle fournit quand même une piste d'audit vérifiable qui était absente dans les attaques Mastra et AntV.
# Bulk maintainer audit script for organizations with many packages
# Lists all maintainers across every package in your org
#!/bin/bash
ORG="yourcompany"
echo "Auditing maintainers for @$ORG scope..."
# Get all packages in the org
PACKAGES=$(npm search --json "@$ORG/" 2>/dev/null | jq -r '.[].name')
for pkg in $PACKAGES; do
echo ""
echo "--- $pkg ---"
npm owner ls "$pkg" 2>/dev/null
done
Run this script quarterly and whenever a contributor leaves the project. Pipe the output to a diff against your authoritative list of current team members. Any account in the npm output that is not in your team list should be revoked immediately.
Exécutez ce script trimestriellement et chaque fois qu'un contributeur quitte le projet. Dirigez la sortie vers un diff par rapport à votre liste officielle des membres actuels de l'équipe. Tout compte dans la sortie npm qui n'est pas dans votre liste d'équipe doit être révoqué immédiatement.
Configuring .npmrc for Scoped Package Security in a Private Registry
Configuration de .npmrc pour la Sécurité des Packages Scopés dans un Registry Privé
Whether you use Verdaccio, GitHub Packages, or a commercial registry, every project consuming private scoped packages needs a properly configured .npmrc. An incorrect or missing .npmrc is the root cause of dependency confusion attacks when using private registries.
Que vous utilisiez Verdaccio, GitHub Packages ou un registry commercial, chaque projet consommant des packages scoped privés a besoin d'un .npmrc correctement configuré. Un .npmrc incorrect ou manquant est la cause principale des attaques de dependency confusion lors de l'utilisation de registries privés.
# .npmrc — project-level, committed to the repository
# This tells npm exactly which registry to use for each scope
# Internal scoped packages: route to your private registry
@yourcompany:registry=https://registry.yourcompany.com
//registry.yourcompany.com/:always-auth=true
# Token injected by CI/CD (never hardcode here)
//registry.yourcompany.com/:_authToken=${NPM_PRIVATE_TOKEN}
# GitHub Packages example (if using GitHub Packages for private packages)
@yourorg:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
# Everything else falls back to the public registry
registry=https://registry.npmjs.org
# Security: verify checksums on all installs
# (enforced by default in npm v7+, but be explicit)
audit=true
fund=false
# Prevent accidental publish to public registry
# Set this in the package.json of each private package:
# "publishConfig": { "registry": "https://registry.yourcompany.com" }
The always-auth=true directive ensures that every request to your private registry includes credentials, even for GET requests (package downloads). This prevents unauthenticated enumeration of your private package list. The ${NPM_PRIVATE_TOKEN} environment variable reference means the token is never stored in the file — it is injected at install time by your CI/CD system or developer's shell profile.
La directive always-auth=true garantit que chaque requête vers votre registry privé inclut des credentials, même pour les requêtes GET (téléchargements de packages). Cela empêche l'énumération non authentifiée de votre liste de packages privés. La référence à la variable d'environnement ${NPM_PRIVATE_TOKEN} signifie que le token n'est jamais stocké dans le fichier — il est injecté au moment de l'installation par votre système CI/CD ou le profil shell du développeur.
Also add "publishConfig" to the package.json of every private package to prevent accidental publication to the public registry:
Ajoutez également "publishConfig" au package.json de chaque package privé pour empêcher la publication accidentelle sur le registry public :
{
"name": "@yourcompany/internal-utils",
"version": "1.0.0",
"private": false,
"publishConfig": {
"registry": "https://registry.yourcompany.com",
"access": "restricted"
}
}
Frequently Asked Questions
Questions Fréquentes
Can npm OIDC Trusted Publishing fully prevent scope takeover attacks?
La publication de confiance OIDC npm peut-elle totalement prévenir les attaques de prise de contrôle de scope ?
OIDC Trusted Publishing eliminates the stored token attack vector (stale credentials, token theft from CI/CD environments). However, it does not protect against pipeline hijack attacks like TanStack (May 2026), where the attacker injected malicious code into the repository itself — causing the legitimate, OIDC-authenticated workflow to publish malicious packages. OIDC is a necessary layer, not a complete solution. You also need code review enforcement, branch protection, and CODEOWNERS to protect the build workflow files themselves.
La publication de confiance OIDC élimine le vecteur d'attaque des tokens stockés (credentials périmés, vol de tokens dans les environnements CI/CD). Cependant, elle ne protège pas contre les attaques de détournement de pipeline comme TanStack (mai 2026), où l'attaquant a injecté du code malveillant dans le dépôt lui-même — amenant le workflow légitime, authentifié OIDC, à publier des packages malveillants. OIDC est une couche nécessaire, pas une solution complète. Vous avez également besoin d'une application de la revue de code, d'une protection de branche et de CODEOWNERS pour protéger les fichiers de workflow de build eux-mêmes.
What is the difference between npm granular tokens and classic tokens?
Quelle est la différence entre les tokens npm granulaires et les tokens classiques ?
Classic npm tokens had no expiry, no scope restriction, and full account access. They are now disabled for creation (November 2025). Granular tokens allow you to specify which packages the token can publish to, which IP ranges are allowed, and set an explicit expiry date (capped at 90 days for write permissions). Always create granular tokens scoped to the minimum necessary packages, and bind them to specific IP ranges or CIDR blocks for your CI/CD runners when possible.
Les tokens npm classiques n'avaient pas d'expiration, pas de restriction de scope et un accès complet au compte. Leur création est désormais désactivée (novembre 2025). Les tokens granulaires vous permettent de spécifier quels packages le token peut publier, quelles plages IP sont autorisées, et de définir une date d'expiration explicite (plafonnée à 90 jours pour les permissions d'écriture). Créez toujours des tokens granulaires scopés aux packages minimaux nécessaires et liez-les à des plages IP ou des blocs CIDR spécifiques pour vos runners CI/CD si possible.
Is Verdaccio safe to use in production in 2026?
Verdaccio est-il sûr à utiliser en production en 2026 ?
Verdaccio is production-ready when properly hardened. The key requirements are: run it behind an HTTPS reverse proxy (never expose it directly), use access: $authenticated on all packages, configure proxy: [] on internal scopes, use JWT tokens with short expiry, enable rate limiting (built-in since v5.4.0), and set up audit logging. Check the Snyk Verdaccio package page regularly for known CVEs in Verdaccio itself — it is an actively maintained project, but like any dependency, it requires monitoring.
Verdaccio est prêt pour la production lorsqu'il est correctement durci. Les exigences clés sont : l'exécuter derrière un proxy inverse HTTPS (ne jamais l'exposer directement), utiliser access: $authenticated sur tous les packages, configurer proxy: [] sur les scopes internes, utiliser des tokens JWT avec une courte expiration, activer le rate limiting (intégré depuis v5.4.0) et configurer la journalisation d'audit. Consultez régulièrement la page du package Verdaccio sur Snyk pour les CVE connues dans Verdaccio lui-même — c'est un projet activement maintenu, mais comme toute dépendance, il nécessite une surveillance.
How do I audit npm maintainer access across hundreds of packages?
Comment auditer les accès mainteneur npm sur des centaines de packages ?
Use the npm CLI: npm owner ls <package> for individual packages, or script the bulk audit pattern shown above. For GitHub-hosted organizations, you can also audit team memberships via the GitHub API: GET /orgs/{org}/teams/{team}/members. Automate this audit as a scheduled CI/CD job that diffs against your authoritative employee/contributor list, and alerts on any account present in npm that is not in the list. Run it weekly at minimum — the Mastra attacker used a stale account that had been inactive since the contributor left the project.
Utilisez le CLI npm : npm owner ls <package> pour les packages individuels, ou scriptez le pattern d'audit en masse montré ci-dessus. Pour les organisations hébergées sur GitHub, vous pouvez également auditer les appartenances aux équipes via l'API GitHub : GET /orgs/{org}/teams/{team}/members. Automatisez cet audit en tant que job CI/CD planifié qui compare avec votre liste officielle d'employés/contributeurs, et alerte sur tout compte présent dans npm qui n'est pas dans la liste. Exécutez-le au minimum hebdomadairement — l'attaquant Mastra a utilisé un compte obsolète inactif depuis que le contributeur avait quitté le projet.
Should I use scoped packages (@company/pkg) for all internal packages?
Dois-je utiliser des packages scopés (@company/pkg) pour tous mes packages internes ?
Yes — unscoped internal packages are the dependency confusion attack surface. If your internal package is named auth-utils (no scope), an attacker can publish auth-utils@100.0.0 to the public registry and win the version resolution race. Scoped packages (@yourcompany/auth-utils) require owning the @yourcompany scope on the public registry to publish there, which an attacker without your credentials cannot do. Migrate all internal unscoped packages to scoped equivalents and register your organization scope on npmjs.com to lock it down proactively.
Oui — les packages internes non scoped constituent la surface d'attaque de dependency confusion. Si votre package interne s'appelle auth-utils (sans scope), un attaquant peut publier auth-utils@100.0.0 sur le registry public et gagner la course de résolution de version. Les packages scoped (@votrecompany/auth-utils) nécessitent de posséder le scope @votrecompany sur le registry public pour y publier, ce qu'un attaquant sans vos credentials ne peut pas faire. Migrez tous les packages internes non scoped vers leurs équivalents scoped et enregistrez le scope de votre organisation sur npmjs.com pour le verrouiller proactivement.
What credentials do npm supply chain attacks steal in 2026?
Quels credentials les attaques supply chain npm volènt-elles en 2026 ?
According to Palo Alto Networks Unit 42's updated npm Threat Landscape report (June 2, 2026), modern npm malware payloads harvest 90+ categories of credentials, including: npm publish tokens (to enable self-propagation to other packages you maintain), AWS/GCP/Azure credentials and STS tokens, SSH private keys, GitHub/GitLab personal access tokens, Kubernetes service account tokens, HashiCorp Vault tokens, Terraform state files (which may contain credentials), database connection strings, shell history (which often contains credentials in plaintext), and AI coding tool credentials (Claude, Cursor, Kiro IDE). A single compromised developer workstation via an infected npm package can expose your entire cloud infrastructure.
Selon le rapport mis à jour de Palo Alto Networks Unit 42 sur le paysage des menaces npm (2 juin 2026), les payloads de malwares npm modernes récoltent 90+ catégories de credentials, notamment : les tokens de publication npm (pour permettre l'auto-propagation vers d'autres packages que vous maintenez), les credentials AWS/GCP/Azure et tokens STS, les clés privées SSH, les tokens d'accès personnels GitHub/GitLab, les tokens de compte de service Kubernetes, les tokens HashiCorp Vault, les fichiers d'état Terraform (qui peuvent contenir des credentials), les chaînes de connexion aux bases de données, l'historique shell (qui contient souvent des credentials en clair) et les credentials d'outils IA de codage (Claude, Cursor, Kiro IDE). Un seul poste développeur compromis via un package npm infecté peut exposer l'intégralité de votre infrastructure cloud.
Monitor Your npm Dependencies — Before the Next Scope Takeover
Surveillez Vos Dépendances npm — Avant la Prochaine Prise de Contrôle de Scope
The @mastra scope was compromised for hours before it was caught. CVE OptiBot scans your package-lock.json and yarn.lock daily, detects newly flagged malicious package versions the moment they appear in OSV.dev, and sends you an immediate alert before any developer runs npm install. No code access required — just your lockfile.
Le scope @mastra a été compromis pendant des heures avant d'être détecté. CVE OptiBot scanne votre package-lock.json et yarn.lock quotidiennement, détecte les nouvelles versions de packages malveillants signalées dès qu'elles apparaissent dans OSV.dev, et vous envoie une alerte immédiate avant qu'un développeur ne lance npm install. Aucun accès au code requis — juste votre lockfile.
Related Articles
Articles connexes
- npm Dependency Confusion Attacks in 2026: Microsoft’s 33-Package Campaign & Prevention Guide →Attaques Dependency Confusion npm en 2026 : Campagne Microsoft & Guide de Prévention →
- npm Lockfile Security in 2026: package-lock.json v3 Integrity & CI/CD Defense Guide →Sécurité du Lockfile npm en 2026 : Intégrité package-lock.json v3 & Guide CI/CD →
- npm Provenance Attestations & SLSA Build Level 3 in 2026 →Attestations de Provenance npm & SLSA Build Level 3 en 2026 →
- npm Supply Chain Canary Tokens in 2026: Detection Guide →Canary Tokens Supply Chain npm en 2026 : Guide de Détection →
- npm Vulnerabilities — CVE Monitoring for Node.js →Vulnérabilités npm — Monitoring CVE pour Node.js →
- CVE Monitoring for Developers →Monitoring CVE pour Développeurs →