Aller au contenu
Categoria: Investigation10 min de lecture

Dependency Confusion et Typosquatting: Defense Pratique pour Equipes Dev

Por Lucas Andrade ·

Comment les politiques de registry, lockfiles et scoping bloquent les paquets malveillants avant le build. Guide technique hands-on de l equipe Basilisk.

Dependency Confusion et Typosquatting: Defense Pratique pour Equipes Dev

En 2021 un chercheur a empoche plus de 130 mille dollars de bug bounty en publiant des paquets portant des noms internes d Apple, Microsoft, PayPal et des dizaines d autres entreprises sur les registres publics npm et PyPI. L attaque n a utilise aucun zero-day: elle a juste exploite la precedence que les gestionnaires de paquets donnent au registry public quand le nom existe des deux cotes. Cinq ans plus tard, les equipes Basilisk trouvent encore ce vecteur ouvert dans sept pipelines audites sur dix. Dependency confusion et typosquatting ne sont pas des curiosites academiques, ce sont la porte d entree bon marche pour compromettre un build entier et, par consequence, chaque client recevant cet artefact. Ce billet decortique les deux vecteurs, deroule la chaine d attaque etape par etape et vous livre une defense a commiter dans votre CI des aujourd hui.

Ce que signifie techniquement le dependency confusion

Le mecanisme est simple et cruel. Vous avez un paquet interne nomme acme-payments-sdk heberge sur un Nexus ou Artifactory prive. Un attaquant decouvre ce nom dans un package.json fuite, un post Stack Overflow ou une couche docker publique, et publie acme-payments-sdk@99.0.0 sur npmjs.com. La prochaine fois que le pipeline lance npm install sans lockfile strict, le resolver choisit la version superieure, car la config par defaut inclut le registry public et SemVer prefere la plus grande version compatible. Voila, du code arbitraire qui tourne dans votre CI avec des credentials AWS, des tokens GitHub et un acces au registry interne. On l a vu sur le terrain dans des missions similaires a Pentest APIs REST et GraphQL : Checklist Technique pour Bug Bounty Legal, ou la surface du build etait plus exploitable que l API elle-meme. La racine est que npm, pip et les autres partagent un namespace plat entre interne et public et, sans config explicite, n exigent aucune preuve d origine.

Le typosquatting comme vecteur a part entiere

Le typosquatting joue dans une autre cour. Au lieu de reprendre le vrai nom, l attaquant enregistre colorss, requets, python-dateutill, lodahs ou djanga. Le payload vit dans un hook postinstall ou directement dans le module importe et s execute des que quelqu un se trompe en tapant ou qu une IA suggere un paquet hallucine (l effet dit slopsquatting). La recherche de Phylum en 2024 a catalogue plus de onze mille paquets malveillants sur PyPI utilisant ce schema en douze mois. Les payloads varient: vol de variables d environnement, minage, installation de RAT, exfiltration par DNS de ~/.aws/credentials. La premiere defense est culturelle: code review obligatoire pour tout changement de dependance, pas de montee de version a l aveugle. Des outils comme Socket, Snyk Advisor et deps.dev signalent deja les paquets fraichement publies, sans historique de mainteneur ou avec des install scripts suspects, vous donnant une signature de risque avant le merge.

La chaine d attaque etape par etape

Comprenez l attaquant et vous comprenez la defense. Phase un, la reconnaissance: l attaquant recolte les noms internes via des recherches GitHub sur @acme, des .npmrc fuites, des sourcemaps du bundle frontend ou des messages d erreur dans des logs de CI publics. Phase deux, la publication: il enregistre le meme paquet avec une version absurdement haute sur le registry public et y glisse un hook preinstall qui frappe une URL de callback. Phase trois, la detonation: votre CI tire le paquet public sur n importe quel build et le hook s execute avec les privileges du runner. Phase quatre, persistance et exfiltration: le code lit les variables d environnement, les tokens OIDC et les deploy keys et les envoie dehors, souvent par DNS ou un POST HTTPS d apparence innocente. C est exactement la que la compromission de supply chain fusionne avec le post-exploitation classique, d ou la meme mentalite qu en reponse a incident.

Lockfiles et hash pinning

Les lockfiles resolvent quatre-vingts pour cent du probleme si on les utilise serieusement. package-lock.json, yarn.lock, pnpm-lock.yaml, poetry.lock, Cargo.lock et go.sum figent non seulement la version mais le hash d integrite. Configurez npm ci, pnpm install --frozen-lockfile, pip install --require-hashes et cargo --locked dans les pipelines. Aucun npm install libre en production, car il peut muter le lockfile. Combine a un .npmrc definissant registry=https://nexus.interne/repository/npm-group/ et always-auth=true, on reduit drastiquement le risque que le resolver aille chercher sur le registry public par erreur. Point clef: un lockfile ne protege que si le runner de CI le respecte et ne le regenere pas. Le pattern mental fait echo a ce qu on couvre dans Supply Chain Security: Signature Sigstore et SBOM Reels en CI/CD sur les SBOM et attestations.

Scoping et registries prives par ecosysteme

Le scoping est l arme definitive contre le dependency confusion en JavaScript. Migrez tous les paquets internes vers @acme/payments-sdk, @acme/auth, @acme/billing. Dans .npmrc, definissez @acme:registry=https://nexus.interne/. Maintenant npm resout ce scope uniquement sur le registry interne, meme si quelqu un publie @acme/payments-sdk sur npmjs (Microsoft reserve les scopes communs depuis 2021). En Python, utilisez des indexes separes: pip --index-url pour les internes et --extra-index-url seulement si vraiment necessaire, car les deux indexes sont fusionnes et la version superieure gagne. Mieux, mirrorez tout via devpi ou Artifactory et ne definissez que index-url. Pour Go, GOPRIVATE=git.acme.com plus la discipline GONOSUMCHECK bloque les requetes vers proxy.golang.org. Ce hardening dialogue directement avec Hardening de Serveur Linux: CIS Benchmark Applique Sans Casser la Prod sur le principe du moindre privilege.

Isolation de la CI et credentials ephemeres

Cote CI, isolez sans pitie. Chaque job de build doit tourner avec des tokens ephemeres, sans acces a la production, avec sortie reseau filtree par un proxy egress n autorisant que le registry interne, github.com et des endpoints connus. OIDC avec credentials short-lived sur GitHub Actions ou GitLab CI elimine les secrets longue duree qu un install hook pourrait voler. Desactivez les install scripts quand c est possible avec npm ci --ignore-scripts et ne les autorisez que pour une allowlist curatee. Faites tourner le build dans un conteneur non-root, filesystem read-only, sans acces au socket docker. Ainsi meme un install hook reussi devient un couteau emousse: il ne trouve aucun secret longue duree, ne peut pas telephoner dehors et ne survit pas a la fin du job. Cette segmentation est moins chere que n importe quel incident et protege aussi le cas ou une dependance legitime est detournee en amont plus tard.

Verification avant installation

Ajoutez une etape de verification pre-install: scripts/check-deps.sh lance npm audit signatures, valide qu aucune dependance n a ete publiee dans les sept derniers jours sans approbation manuelle (un cooldown contre les detournements frais), et confronte les paquets a une allowlist. Ajoutez osv-scanner contre la base OSV et Socket dans la CI, qui montre les diffs de comportement entre versions: nouveaux appels reseau, nouvel acces au filesystem, install scripts fraichement ajoutes. Un paquet qui importe soudain child_process ou contacte une IP est bloque et part en revue manuelle. L equipe Datadog a publie un rapport en 2025 montrant que soixante-deux pour cent des compromissions de supply chain auraient ete bloquees avec ces trois regles combinees. Aucun outil seul n est une balle d argent, mais chainer cooldown, verification de signature et diff de comportement ferme les chemins les plus courants.

Surveillance continue et protection des noms

La surveillance continue ferme la boucle. Configurez des alertes Sigstore Rekor pour toute publication portant le nom de votre organisation, enregistrez defensivement les domaines et noms de paquet typo-squatting de votre produit (acme-cloud, acme-coud, acmecloud), et maintenez un inventaire de SBOM signes via cosign pour chaque release. Quand un paquet suspect apparait, vous avez deja la preuve pour le takedown et les donnees pour la reponse a incident, dans le style montre dans DFIR sous Linux: Triage Vivant avec UAC et Velociraptor. Reservez proactivement les noms de vos paquets internes comme placeholders vides sur le registry public pour que personne ne les squatte. Formez l equipe a remonter tout nouveau warning d install script au lieu de l ignorer par reflexe, car ce warning est souvent le seul signal avant la compromission.

Erreurs courantes en pratique

Cinq pieges reviennent dans presque chaque audit. Un: --extra-index-url par defaut en Python, qui melange interne et PyPI et ouvre le vecteur en grand. Deux: des lockfiles regeneres au lieu d etre respectes en CI, parce que quelqu un a laisse npm install a la place de npm ci. Trois: des paquets internes sans scope, si bien que n importe quel namespace public les eclipse. Quatre: des install scripts autorises globalement alors que quatre-vingt-dix pour cent des builds n en ont pas besoin. Cinq: des tokens npm ou PyPI longue duree dans la CI qu un hook exfiltre et qui restent valides des mois. Chacun a lui seul suffit a une compromission; ensemble, c est une porte de grange ouverte. La bonne nouvelle est que chacun se corrige en moins d une journee et aucun n exige de changer le code du produit.

Checklist pratique

Traitez cette liste aujourd hui. Un: migrez tous les paquets npm internes vers un @scope lie au registry interne. Deux: imposez npm ci, --frozen-lockfile, --require-hashes ou --locked dans chaque pipeline. Trois: en Python n utilisez que index-url pointant sur le mirror interne, pas de --extra-index-url. Quatre: definissez GOPRIVATE pour tous les modules Go internes. Cinq: desactivez les install scripts par defaut, tenez une allowlist. Six: OIDC au lieu de tokens de registry longue duree. Sept: un proxy egress dans la CI avec allowlist. Huit: osv-scanner, npm audit signatures et Socket comme gate de merge. Neuf: reservez defensivement les noms internes sur le registry public. Dix: alertes Rekor sur le nom de l organisation. Cochez ces dix points et vous avez verrouille la porte d entree bon marche.

FAQ

Un lockfile suffit-il contre le dependency confusion ? Non. Le lockfile protege les dependances existantes, mais des que vous ajoutez une nouvelle dependance interne ou regenerez le lockfile, la precedence du registry mord a nouveau. Lier le scope au registry interne et un proxy egress sont la solution structurelle; le lockfile est la deuxieme couche.

Le typosquatting est-il seulement un probleme npm et PyPI ? Non. RubyGems, Maven Central, NuGet, Crates et meme les images Docker Hub sont concernes. L approche defensive est la meme partout: un mirror interne curate, un diff de comportement entre versions, un cooldown pour les artefacts fraichement publies et une revue humaine a chaque changement de dependance.

Conclusion

Dependency confusion et typosquatting ne sont pas des attaques exotiques, ce sont la maniere la moins chere de passer a cote d une organisation sans toucher une seule ligne de son vrai code. La defense est connue, bon marche et applicable aujourd hui: liaison de scope, hash pinning, CI isolee avec credentials ephemeres, verification avant installation et surveillance continue. Takeaway pratique: aujourd hui meme, auditez vos .npmrc, .pip.conf et go env. Si vous ne pouvez pas dire en trente secondes de quel registry vient chaque dependance, vous etes deja vulnerable. Les attaquants n ont pas besoin d un zero-day; ils attendent juste que quelqu un laisse l ordre du registry non configure.

Related posts

Nenhum comentário ainda

Seja o primeiro a comentar.

Deixe seu comentário

Entre com sua conta Canverly para comentar. Você pode usar a mesma conta em qualquer site da rede.

Entrar com Canverly