Skip to Content
SécuritéPartie 12 — Dépendances & supply chain12.2 — Typosquatting & lockfiles

Chapitre 12.2 — Typosquatting & lockfiles

⏱️ TL;DR — Au-delà des failles dans des paquets légitimes (chapitre 12.1), il y a les paquets volontairement malveillants ou compromis. Typosquatting : un paquet au nom proche d’un populaire (crossenv pour cross-env) que tu installes par erreur de frappe → il exécute du code hostile. Mainteneur compromis / dépendance détournée : un paquet légitime dont une nouvelle version est piégée (compte du mainteneur piraté, injection de code). Scripts post-install : npm install exécute des scripts (postinstall) des paquets — un vecteur d’exécution de code à l’installation même. Défenses : verrouiller (lockfile + installation exacte), vérifier ce qu’on ajoute (nom, mainteneur, popularité), limiter les scripts, et réduire le nombre de dépendances.

🎯 Objectifs

  • Reconnaître le typosquatting et vérifier un paquet avant de l’ajouter.
  • Comprendre le risque des dépendances compromises (mainteneur piraté, version piégée).
  • Comprendre le danger des scripts post-install et comment le limiter.
  • Verrouiller les versions (lockfile) et installer de façon reproductible.

Typosquatting : le paquet au nom piège

Le typosquatting consiste à publier un paquet malveillant sous un nom très proche d’un paquet populaire, en pariant sur les fautes de frappe ou la confusion : cross-envcrossenv, lodashlodahs, un nom avec un tiret en trop/en moins, une orthographe voisine. Le développeur pressé tape le mauvais nom, l’installe, et exécute du code hostile (vol de variables d’environnement, de tokens, backdoor) — souvent dès l’installation via un script post-install.

# ❌ Faute de frappe -> paquet malveillant npm install crossenv # au lieu de cross-env (exemple historique reel)

Parade : vérifier le nom exact avant d’installer (copier depuis la doc officielle, pas de mémoire), et regarder les signaux du paquet :

  • Popularité : nombre de téléchargements, d’étoiles, d’utilisateurs. Un paquet « officiel » a une adoption massive ; un typosquat est souvent récent et peu téléchargé.
  • Mainteneur / dépôt : correspond-il au projet légitime ? Lien vers un dépôt actif ?
  • Ancienneté et historique : un paquet créé il y a trois jours qui « ressemble » à un standard est suspect.

Dépendances compromises : le paquet légitime… piégé

Plus insidieux : un paquet légitime et populaire dont une nouvelle version est piégée. Scénarios réels :

  • Compte de mainteneur compromis (mot de passe faible, pas de MFA) : un attaquant publie une version malveillante sous le vrai nom.
  • Transfert de projet à un mainteneur mal intentionné, qui injecte du code.
  • Dépendance transitive d’un de tes paquets qui est, elle, compromise — tu ne l’as même pas choisie directement.

Le code malveillant fait typiquement : exfiltrer des secrets (variables d’env, .npmrc, clés), installer une backdoor, ou cibler spécifiquement certains environnements (CI, prod). Comme le paquet est légitime par ailleurs, la compromission peut passer inaperçue un temps. C’est le scénario le plus difficile — d’où l’importance du verrouillage (ci-dessous) et de la vigilance sur les mises à jour (ne pas auto-merger aveuglément — chapitre 12.1).

Scripts post-install : du code à l’installation

Point crucial et sous-estimé : npm install exécute des scripts définis par les paquets (preinstall, install, postinstall). Ces scripts s’exécutent sur ta machine (ou ta CI) avec tes droits, au moment de l’installation — avant même que ton appli tourne. C’est un vecteur privilégié pour le code malveillant d’un paquet typosquatté ou compromis : voler les variables d’environnement de la CI, les tokens, poser une backdoor.

Mesures :

  • Auditer / limiter les scripts : npm install --ignore-scripts désactive l’exécution des scripts d’installation (à utiliser quand aucun paquet légitime n’en a besoin ; certains, comme des binaires natifs, en requièrent — à évaluer). On peut configurer une allow-list de scripts autorisés selon l’outillage.
  • Isoler l’installation : installer dans un environnement contrôlé (conteneur, CI avec droits minimaux — Partie 14), pas sur un poste ayant accès à des secrets sensibles.
  • Surveiller les paquets qui ont des scripts d’install (des outils listent les postinstall).

⚠️ Piège — Sous-estimer les scripts post-install : beaucoup de devs pensent qu’un paquet malveillant ne fait des dégâts que s’ils l’utilisent dans le code. Faux — un postinstall s’exécute à l’npm install, avant tout usage, avec tes droits (et ceux de ta CI, souvent riche en secrets et en accès). Un simple npm install d’un paquet piégé peut exfiltrer les secrets de ta CI. D’où l’intérêt d’--ignore-scripts quand c’est possible, d’installations isolées, et de CI aux droits minimaux.

Verrouiller : lockfile et installation reproductible

La défense centrale contre « une version piégée arrive silencieusement » est le verrouillage. Les gestionnaires produisent un lockfile (package-lock.json, composer.lock) qui fige exactement les versions installées (avec leurs empreintes d’intégrité). En committant le lockfile et en installant à partir de lui, on garantit que tout le monde (et la CI, et la prod) installe exactement le même code — pas une version différente résolue par les plages ^/~.

# ✅ Installation EXACTE et reproductible depuis le lockfile npm ci # Node : installe strictement package-lock.json (ideal en CI/prod) composer install # PHP : installe strictement composer.lock (sans --update) # ❌ Peut resoudre des versions differentes du lockfile npm install # en CI : evite (peut deriver des plages ^/~)
  • Commit le lockfile et installe avec npm ci (ou composer install) en CI/prod : reproductibilité et intégrité (le lockfile contient des hashes vérifiés).
  • Contrôle les mises à jour : une nouvelle version n’entre que par une modification explicite du lockfile (une PR de MAJ, revue) — pas silencieusement. C’est ce qui te laisse une fenêtre de revue avant qu’une version piégée n’atteigne la prod.

💡 Réflexe — Le lockfile n’est pas un détail d’outillage, c’est un contrôle de sécurité : il fige ce qui s’exécute et rend visible tout changement de dépendance (via le diff du lockfile en revue). Commit-le, installe avec npm ci/composer install, et regarde les diffs de lockfile dans les PR — un ajout de dépendance transitive inattendu ou un changement de source mérite un coup d’œil. Reproductibilité = intégrité = sécurité.

🎯 Côté attaquant — L’attaquant supply chain vise l’effet de levier : compromettre un paquet (typosquat qui piège les distraits, ou prise de contrôle d’un paquet populaire) pour atteindre toutes les applis qui l’installent. Sa charge s’exécute souvent en postinstall (dès l’install, avant usage) et cible les secrets de CI/dev (tokens npm, clés cloud, .env) — car une CI compromise permet ensuite d’empoisonner d’autres paquets ou déploiements. Il compte sur les installs non verrouillées (npm install qui prend la dernière version) et les auto-merges aveugles pour glisser sa version piégée.

🧭 Sur FormaCampus — FormaCampus commit ses lockfiles et installe partout avec npm ci / composer install (jamais npm install en CI/prod) — reproductibilité et intégrité garanties. L’ajout d’une dépendance passe par une revue (nom exact vérifié contre la doc officielle, mainteneur, popularité, historique — anti-typosquatting) et le diff du lockfile est examiné dans chaque PR. La CI installe avec des droits minimaux (pas de secrets de prod), envisage --ignore-scripts là où c’est possible, et les mises à jour (Dependabot) ne sont pas auto-mergées aveuglément (revue + tests, surtout pour les majeures). Ainsi, une version piégée ne peut pas atteindre la prod « silencieusement ».

✏️ Exercices

Exercice 1 — Repère le piège. Un dev veut installer la bibliothèque de dates dayjs et tape npm install day-js. Quels signaux devraient l’alerter, et comment éviter ce type d’erreur ?

✅ Solution

day-js (avec un tiret) n’est pas dayjs : c’est probablement un typosquat. Signaux d’alerte à vérifier avant d’installer : (1) popularitédayjs a des millions de téléchargements/semaine ; un typosquat en a très peu ; (2) mainteneur / dépôt — correspond-il au projet officiel ? ; (3) ancienneté / historique — un paquet récent imitant un standard est suspect. Pour éviter l’erreur : copier le nom exact depuis la documentation officielle (pas de mémoire), vérifier la page du paquet (téléchargements, dépôt lié) avant install. Et comme filet : lockfile + revue du diff, CI aux droits minimaux (au cas où un postinstall malveillant s’exécuterait). Une simple faute de frappe peut exécuter du code hostile — d’où la vérification systématique du nom.

Exercice 2 — npm install vs npm ci en CI. Explique pourquoi utiliser npm install dans un pipeline de déploiement est un risque de sécurité, et ce qu’il faut faire.

✅ Solution

npm install re-résout les versions à partir des plages du package.json (^/~) : il peut donc installer une version différente de celle du lockfile — une version plus récente non testée, voire une version compromise publiée entre-temps. Le déploiement n’est alors pas reproductible et échappe à la revue. Ce qu’il faut faire : utiliser npm ci (ou composer install), qui installe exactement le lockfile committé (avec vérification des hashes d’intégrité) — même code partout, tout changement de dépendance passant par une modification explicite et revue du lockfile. La reproductibilité (via le lockfile + npm ci) est un contrôle de sécurité : elle fige ce qui s’exécute et rend visible tout changement.

🧠 Quiz de révision

1. Qu’est-ce que le typosquatting ?

Publier un paquet malveillant sous un nom très proche d’un paquet populaire (faute de frappe, orthographe voisine) pour piéger les développeurs distraits qui l’installent — le code hostile s’exécute alors chez eux (souvent via un script post-install). Parade : vérifier le nom exact et les signaux (popularité, mainteneur, ancienneté).

2. Comment un paquet légitime peut-il devenir malveillant ?

Par compromission du mainteneur (compte piraté, pas de MFA), transfert à un acteur mal intentionné, ou via une dépendance transitive compromise. Une nouvelle version piégée est publiée sous le vrai nom et peut passer inaperçue. D’où l’importance du verrouillage et de ne pas auto-merger aveuglément.

3. Pourquoi les scripts post-install sont-ils dangereux ?

Parce que npm install exécute ces scripts (postinstall…) à l’installation, avec tes droits (et ceux de ta CI, riche en secrets) — avant tout usage du paquet. Un paquet piégé peut ainsi exfiltrer les secrets de CI ou poser une backdoor dès l’install. Parades : --ignore-scripts quand possible, installations isolées, CI aux droits minimaux.

4. À quoi sert le lockfile du point de vue sécurité ?

Il fige exactement les versions installées (avec leurs hashes d’intégrité) : installé avec npm ci/composer install, il garantit que tout le monde exécute le même code, et rend visible tout changement de dépendance (diff du lockfile en revue). C’est un contrôle d’intégrité et de reproductibilité — donc de sécurité.

5. Pourquoi préférer npm ci à npm install en CI/prod ?

npm ci installe strictement le lockfile (reproductible, hashes vérifiés) ; npm install peut re-résoudre des versions différentes (plages ^/~), introduisant une version non testée ou compromise, hors revue. La reproductibilité fige ce qui s’exécute et laisse une fenêtre de revue avant la prod.


Chapitre suivant : SRI, provenance & SBOM — garantir l’intégrité des ressources externes, tracer l’origine du code, et inventorier ses composants.

Last updated on