Retour au blogSécurité

Malware nord-coréen caché dans un tailwind.config.js : anatomie d'une attaque

CZSyn
4 juillet 2026
7 min

Un malware nord-coréen dissimulé dans un tailwind.config.js a infecté plusieurs dépôts. Comment auditer vos configs JS avant qu'elles ne vous piègent.

Ecran de code montrant une analyse de sécurité sur un fichier de configuration JavaScript
Ce qu'il faut retenir
  1. Un chercheur en sécurité a découvert un malware attribué à des acteurs nord-coréens dissimulé dans le fichier tailwind.config.js de son projet, caché après des centaines d'espaces vides pour échapper à toute lecture visuelle du fichier.
  2. Le code malveillant fonctionnait comme un chargeur en plusieurs étapes : tableau de chaînes mélangées, décodage base64 via atob(), exécution dynamique, un schéma classique d'obfuscation JavaScript utilisé pour dissimuler la charge réelle hors du fichier.
  3. L'infection a touché trois dépôts et fait tourner six processus inconnus, avec à la clé un commit Git que l'auteur n'avait jamais rédigé, l'obligeant à arrêter des processus en production et à faire une rotation complète de ses identifiants.

Résumé généré par IA

Le 21 juin 2026, un chercheur en sécurité publiait sur InfoSec Write-ups le récit d'une découverte qu'il n'avait pas cherchée : un malware attribué à des acteurs nord-coréens, dissimulé dans le fichier tailwind.config.js d'un de ses projets Node.js. Pas dans une dépendance douteuse au fond de node_modules. Pas dans un script post-install exotique. Dans un fichier de configuration que la quasi-totalité des développeurs touchent une fois, au moment du setup, puis n'ouvrent plus jamais.

Trois jours après avoir repéré l'anomalie, l'auteur tuait des processus en production à deux heures du matin, faisait tourner l'intégralité de ses identifiants, et tombait sur un commit Git signé de son propre nom qu'il n'avait jamais écrit. Voici comment ce piège a fonctionné, et surtout comment vérifier qu'il n'est pas déjà installé chez vous.

Un fichier qu'on ne relit jamais après le setup

Rappel rapide pour ceux qui découvrent : tailwind.config.js sert à définir vos couleurs, vos breakpoints, vos plugins Tailwind CSS. On l'ouvre en général une fois, au lancement du projet, souvent parce qu'un outil comme create-next-app ou un template de démarrage l'a généré à notre place. Ensuite, plus personne n'y touche. C'est exactement ce qui en fait une cible de choix : contrairement à package.json ou à node_modules, ce fichier n'est scanné par aucun outil de sécurité classique. npm audit, Dependabot ou Snyk vérifient des dépendances référencées, pas votre propre code de configuration.

Anatomie de l'attaque : comment le malware s'est caché

Le chercheur copiait simplement ses anciens tokens de couleur dans un tailwind.config.js tout neuf. Le premier signal d'alerte a été bête : le collage a mis une seconde de trop pour cinq lignes de configuration. En diffant le fichier en ligne, il découvre un mur de code obfusqué, placé après des centaines d'espaces vides, juste assez pour qu'un éditeur de texte classique ne le montre jamais à l'écran sans avoir besoin de scroller ou de differ explicitement.

La configuration Tailwind visible en tête de fichier est parfaitement légitime : couleurs personnalisées, dark mode en classe, chemins de contenu cohérents. C'est un leurre efficace, tout développeur qui ouvre le fichier voit un config.js normal et referme l'éditeur. Le code malveillant, lui, suit un schéma d'obfuscation classique : un tableau de chaînes de caractères mélangées, décodé au runtime par une fonction dédiée, une IIFE asynchrone qui s'attache à des variables globales, et un payload encodé en base64 décodé via atob() puis exécuté dynamiquement. Concrètement, le fichier ne contient pas le malware complet : il contient un chargeur, dont le seul travail est de récupérer et d'exécuter l'étape suivante, potentiellement différente à chaque exécution.

// Schéma simplifié du procédé observé (illustratif, pas le code réel)
module.exports = { theme: { extend: { colors: { primary: '#c90101' } } } };
// ... des centaines d'espaces vides ...
global['_x'] = require;
(async () => {
  const payload = atob("...base64...");
  eval(payload); // exécute l'étape suivante, hors du fichier
})();

Trois jours plus tard : rotation de crédentiels à deux heures du matin

Le temps de comprendre ce qu'il regardait, l'auteur a découvert une infection confirmée sur trois de ses dépôts, six processus inconnus tournant sur ses machines, et un commit Git portant son nom qu'il n'avait jamais rédigé. La suite s'est jouée en pleine nuit : arrêt des processus suspects en production, rotation de tous ses identifiants, et reprise ligne par ligne de chaque dépôt touché pour comprendre l'étendue réelle de la compromission.

Pourquoi les fichiers de config JS sont l'angle mort de la supply chain

Le point le plus intéressant pour vous n'est pas le malware en lui-même, c'est l'endroit où il se cache. Webpack, Vite, Tailwind, Next.js : tous ces outils reposent sur des fichiers de configuration en JavaScript exécutable, pas en JSON ou en YAML. Un *.config.js peut légalement contenir n'importe quel code : require, fetch, accès au système de fichiers. Personne ne s'en étonne, puisque c'est la nature même du format. Résultat : un fichier de config est un des rares endroits d'un projet où du code arbitraire s'exécute sans jamais passer par une revue de dépendance, un scan de vulnérabilité, ni même, la plupart du temps, une relecture humaine.

Ajoutez à ça une habitude très répandue : recopier un tailwind.config.js ou un vite.config.js trouvé sur un template GitHub, un tutoriel, ou hérité d'un projet précédent, sans jamais vérifier sa provenance. C'est exactement la même logique que copier un script bash trouvé sur un forum et l'exécuter en root.

Comment auditer vos fichiers de config avant qu'ils ne vous piègent

Trois réflexes simples permettent de fermer cet angle mort sans outillage lourd. D'abord, traquer les lignes anormalement longues, signature classique de code obfusqué compressé sur une seule ligne :

grep -rnE '.{400,}' --include='*.config.js' --include='*.config.ts' .

Ensuite, chercher les fonctions typiques d'un chargeur dynamique dans un fichier qui n'a aucune raison d'en contenir :

grep -rnE 'atob\(|eval\(|new Function\(|global\[' --include='*.config.js' --include='*.config.ts' .

Enfin, si un doute subsiste sur un dépôt existant, vérifiez l'historique des commits pour repérer une signature qui ne correspond à aucune de vos sessions de travail :

git log --format='%h %an %ae %ad %s'

Au-delà de ces commandes, le vrai changement d'habitude est ailleurs : intégrez vos fichiers de configuration (tailwind.config.js, webpack.config.js, vite.config.js, next.config.js) à votre revue de code au même titre qu'un fichier métier, et ne les recopiez jamais depuis une source dont vous ne connaissez pas l'origine.

Notre lecture chez CZSyn

Sur les projets que nous reprenons pour nos clients, une part non négligeable des fichiers de configuration vient de templates hérités, de précédents prestataires, ou de scaffolding généré une fois pour toutes et jamais réaudité. Cette affaire confirme un point qu'on répète depuis longtemps à nos clients PME : la sécurité d'un projet Node.js ne se limite pas à npm audit. Un fichier de configuration exécutable est du code, avec les mêmes risques qu'un fichier applicatif, et mérite la même vigilance.

Pour une petite structure sans équipe sécurité dédiée, le réflexe le plus rentable reste le plus simple : ajouter les fichiers *.config.js à la checklist de revue de code, et refuser tout template dont on ne connaît pas la source exacte. C'est aussi le type de vérification que nous intégrons systématiquement lors d'un audit de projet existant.

Un doute sur la sécurité de vos fichiers de configuration ?

Nous auditons gratuitement vos projets Node.js (Tailwind, Webpack, Vite, Next.js) pour repérer les angles morts de sécurité, et intervenons en développement sur-mesure ou en dépannage si une compromission est suspectée.

29 AVIS 5/5 · +200 PROJETS LIVRÉS · RÉPONSE EXPRESS

Sources primaires

Un projet en tête ?

Discutons de votre projet et voyons comment nous pouvons vous aider.

Nous contacter