OWASP Top 10 en pratique : de Shai-Hulud aux défenses NestJS
Le ver Shai-Hulud a infecté des centaines de packages npm et ciblé les outils IA comme Claude Code. On revoit l'OWASP Top 10 à travers ce cas réel, et comment s'en prémunir concrètement avec NestJS.
L'OWASP Top 10 est souvent lu comme une liste académique qu'on coche vite fait avant de retourner coder. Big mistake. Le ver Shai-Hulud, qui a compromis des centaines de packages npm depuis septembre 2025 et refait surface en 2026 en ciblant directement les outils de développement assistés par IA, en est l'illustration la plus concrète de la décennie — et un bon rappel qu'AppSec, ce n'est pas juste du papier. Voici le Top 10 revisité à travers ce cas réel, avec les défenses à mettre en place côté NestJS. Zero vuln, comme on dit ici.
Qu'est-ce que Shai-Hulud ?
Shai-Hulud est un ver auto-propagateur qui s'attaque à l'écosystème npm. Son mode opératoire :
- Il compromet un package populaire (via un token de mainteneur volé ou une dépendance déjà infectée).
- Un script post-install malveillant s'exécute silencieusement à l'installation (
npm install). - Ce script scanne la machine à la recherche de secrets : clés SSH, tokens npm/GitHub, credentials cloud, clés d'API LLM.
- Il exfiltre ces secrets, souvent via des dépôts GitHub publics utilisés comme "dead-drop" (point de dépôt discret).
- Avec les tokens npm volés, il republie automatiquement d'autres packages infectés — d'où la propagation en ver.
La vague la plus récente va plus loin : de faux serveurs MCP (Model Context Protocol) embarquent des instructions de prompt-injection destinées aux assistants IA type Claude Code, pour leur faire exfiltrer discrètement des secrets locaux sans alerter le développeur. Un cas documenté a même détourné l'intégration GitHub de Claude Code pour injecter des workflows CI malveillants et voler des tokens OIDC npm.
Ce n'est pas un bug isolé — c'est un cas d'école qui traverse presque tout l'OWASP Top 10.
A03:2021 — Injection
Le point d'entrée de Shai-Hulud est un script postinstall exécuté sans contrôle. Ce n'est pas une injection SQL classique, mais le principe est identique : du code non fiable s'exécute avec les privilèges de l'hôte.
Défense NestJS : ce n'est pas NestJS qui protège ici, c'est la configuration npm/CI. Désactivez les scripts de post-install par défaut :
npm config set ignore-scripts true
Et validez systématiquement les entrées utilisateur côté API avec les ValidationPipe et class-validator :
// main.ts
app.useGlobalPipes(new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true
}))
A06:2021 — Composants vulnérables et obsolètes
C'est le cœur du problème Shai-Hulud : des centaines de packages tiers compromis, souvent des dépendances indirectes (keyv, flat-cache...) que personne n'audite manuellement.
Défense NestJS :
- Auditez et épinglez les versions exactes (pas de
^ou~) danspackage.json, et committez le lockfile. - Automatisez l'audit dans la CI :
npm audit --audit-level=high
npx socket-security scan # détection de comportements suspects (scripts, réseau)
- Activez le Provenance npm et la vérification de signature pour vos propres publications :
npm publish --provenance
- Utilisez Dependabot ou Renovate avec une revue humaine obligatoire sur les mises à jour majeures, plutôt qu'un merge automatique.
A08:2021 — Défaillances d'intégrité des logiciels et des données
C'est la catégorie qui correspond le plus précisément à une attaque de supply chain : une CI/CD ou un pipeline de build qui fait confiance à du contenu non vérifié (packages, workflows GitHub Actions injectés).
Défense NestJS / CI :
- Verrouillez vos GitHub Actions par SHA complet, jamais par tag mutable :
# mauvais
- uses: actions/checkout@v4
# bon
- uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3
- Isolez les builds dans des environnements éphémères sans accès aux secrets de production.
- Séparez strictement les tokens : un token CI en lecture seule pour les PR externes, un token de déploiement séparé et scoppé au minimum nécessaire.
A02:2021 — Défaillances cryptographiques
Les secrets exfiltrés par Shai-Hulud (clés API, tokens) n'ont de valeur que s'ils traînent en clair. Beaucoup de projets Node/NestJS stockent encore des clés API directement dans .env commité ou dans des variables d'environnement en clair sur le serveur.
Défense NestJS :
- Utilisez un secret manager (Vault, AWS Secrets Manager, Doppler) plutôt que des fichiers
.enven production. - Avec
@nestjs/config, validez et typez les variables d'environnement au démarrage pour détecter immédiatement une config manquante ou incohérente :
ConfigModule.forRoot({
validationSchema: Joi.object({
NUXT_SESSION_SECRET: Joi.string().min(32).required(),
DATABASE_URL: Joi.string().uri().required()
})
})
- Faites tourner les secrets régulièrement, et immédiatement après tout incident de type Shai-Hulud touchant une dépendance de votre stack.
A05:2021 — Mauvaise configuration de sécurité
Un serveur NestJS par défaut expose des en-têtes et des comportements qui facilitent la reconnaissance par un attaquant (fingerprinting, CORS trop permissif, absence de rate limiting).
Défense NestJS :
import helmet from 'helmet'
app.use(helmet())
app.enableCors({ origin: ['https://monblog.com'], credentials: true })
Ajoutez un rate limiting global pour ralentir toute tentative d'exfiltration ou de brute force via vos endpoints :
import { ThrottlerModule } from '@nestjs/throttler'
ThrottlerModule.forRoot([{ ttl: 60000, limit: 100 }])
A09:2021 — Carences des systèmes de journalisation et de surveillance
Une bonne partie de la propagation de Shai-Hulud a été détectée tardivement faute de monitoring sur les comportements anormaux (publications npm inhabituelles, connexions sortantes inattendues depuis les runners CI).
Défense NestJS :
- Loggez les événements sensibles (authentification, changement de permissions, accès aux secrets) avec un logger structuré (
pino,winston) exporté vers un SIEM. - Surveillez les connexions réseau sortantes de vos environnements CI — un runner qui contacte un dépôt GitHub inconnu pendant un
npm installest un signal fort.
Check-list de prévention Shai-Hulud
-
ignore-scripts=truepar défaut sur les postes dev et en CI - Lockfile committé, versions épinglées, audit automatisé en CI
- GitHub Actions verrouillées par SHA, pas par tag
- Secrets en secret manager, jamais en
.envcommité - Tokens npm/GitHub scoppés au strict minimum, rotation régulière
- Monitoring des publications npm et du trafic sortant des runners CI
- Vigilance sur les serveurs MCP tiers : n'installez que des serveurs MCP dont la source est auditée, jamais depuis un lien non vérifié
Shai-Hulud n'est pas une faille NestJS ni une faille Node — c'est un rappel que la chaîne de confiance d'un projet moderne dépasse largement son propre code. L'OWASP Top 10 reste le meilleur référentiel pour structurer cette vigilance, à condition de l'appliquer aussi à ses dépendances et à sa CI, pas seulement à son code applicatif.
TypeScript le jour, AppSec le soir : blindez ce que vous construisez, et gardez toujours une pensée pour vos secrets avant qu'un ver ne le fasse à votre place. One love, clean architecture, zero vuln.