Bitwarden CLI compromis dans la campagne de chaîne d’approvisionnement Checkmarx en cours
(socket.dev)- Le package Bitwarden CLI pour npm a été compromis dans le cadre de la campagne d’attaque de chaîne d’approvisionnement Checkmarx en cours, et la portée confirmée à ce stade se limite à la build
@bitwarden/cli2026.4.0 - Le code malveillant
bw1.jsinclus dans le package utilise la même infrastructure et les mêmes techniques d’obfuscation, commeaudit.checkmarx[.]cx/v1/telemetry, et s’aligne avec des indices d’une compromission CI/CD via une GitHub Action compromise - La collecte ne vise pas seulement les tokens GitHub, mais aussi les identifiants AWS, Azure et GCP,
.npmrc, les clés SSH, les variables d’environnement et jusqu’aux fichiers de configuration Claude/MCP - Les informations volées servent à créer des dépôts GitHub publics et à y effectuer des commits, à propager la redistribution via des tokens npm, à injecter des workflows, et incluent aussi des fonctions de persistance comme la modification de
~/.bashrcet~/.zshrc - Les organisations qui utilisent Bitwarden CLI doivent traiter cet incident comme une exposition d’identifiants et une compromission CI/CD, en accordant une importance particulière à l’examen des logs CI et à la rotation des secrets potentiellement exposés
Vue d’ensemble
- Le package npm Bitwarden CLI a été compromis dans le cadre de l’attaque de chaîne d’approvisionnement Checkmarx en cours, et la version ciblée confirmée est
@bitwarden/cli2026.4.0- Le code malveillant se trouvait dans
bw1.js, inclus dans le package - Le vecteur d’attaque concorde avec des indices d’utilisation d’une GitHub Action compromise dans le pipeline CI/CD de Bitwarden, et correspond au schéma de campagne observé dans d’autres dépôts
- Le code malveillant se trouvait dans
- À ce stade, la portée confirmée est limitée à la build Bitwarden CLI, et la compromission suit le vecteur de chaîne d’approvisionnement GitHub Actions identifié dans la campagne Checkmarx
- Seul le package CLI pour npm est concerné
- L’extension Chrome, le serveur MCP et les autres distributions officielles ne sont pour l’instant pas confirmés comme affectés
- L’enquête se poursuit, et une analyse technique complète, les versions affectées, les indicateurs de compromission et les consignes de réponse seront publiés ultérieurement
- Si vous utilisez Bitwarden CLI, il faut examiner les logs CI et faire tourner les secrets susceptibles d’avoir été exposés
Analyse technique
- La charge utile malveillante
bw1.jspartage l’infrastructure centrale dumcpAddon.jsde Checkmarx analysé la veille- Elle utilise le même endpoint C2
audit.checkmarx[.]cx/v1/telemetryet est obfusquée avec__decodeScrambledet la graine0x3039 - Elle exfiltre aussi via des commits passant par l’API GitHub et vole des tokens npm pour redistribution via le registre npm
- Elle utilise le même endpoint C2
- La structure de la charge utile embarquée appartient également à la même famille
- À l’intérieur d’une structure gzip+base64 se trouve un script Python qui ratisse la mémoire de
Runner.Workerdans GitHub Actions pour viser les tokens GitHub - Un loader
setup.mjspour les packages npm redistribués, un workflow YAML GitHub Actions, une clé publique RSA codée en dur et une chaîne de manifeste idéologique sont également inclus
- À l’intérieur d’une structure gzip+base64 se trouve un script Python qui ratisse la mémoire de
- Le périmètre de collecte d’identifiants est très large
- Les tokens GitHub sont collectés via le scraping de la mémoire de
Runner.Workeret des variables d’environnement - Les identifiants AWS sont recherchés dans les fichiers
~/.aws/et dans les variables d’environnement - Les tokens Azure sont récupérés via
azd, et les identifiants GCP viagcloud config config-helper .npmrc, les clés SSH, les variables d’environnement et les fichiers de configuration Claude/MCP font aussi partie des cibles
- Les tokens GitHub sont collectés via le scraping de la mémoire de
- La méthode d’exfiltration via GitHub a également été observée en détail
- Le malware crée sous le compte de la victime un dépôt public suivant la convention de nommage inspirée de Dune
{word}-{word}-{3digits} - Il y commit les résultats chiffrés, avec un message de commit contenant le marqueur
LongLiveTheResistanceAgainstMachinesainsi que le token
- Le malware crée sous le compte de la victime un dépôt public suivant la convention de nommage inspirée de Dune
- Le mécanisme de propagation dans la supply chain est lui aussi présent
- Avec les tokens npm volés, il identifie les packages sur lesquels il a des droits d’écriture et les republie avec un hook
preinstallinjecté - Il injecte aussi des workflows GitHub Actions pour collecter davantage de secrets de dépôt
- Avec les tokens npm volés, il identifie les packages sur lesquels il a des droits d’écriture et les republie avec un hook
- Un kill switch basé sur la locale russe est présent
- Si la locale système commence par
"ru", le malware s’arrête silencieusement - Il vérifie
Intl.DateTimeFormat().resolvedOptions().localeainsi que les variables d’environnementLC_ALL,LC_MESSAGES,LANGUAGEetLANG
- Si la locale système commence par
- L’environnement d’exécution est Bun v1.3.13, téléchargé depuis GitHub Releases
Différences par rapport à l’incident Checkmarx
bw1.jscontient des indicateurs de compromission supplémentaires qui n’apparaissaient pas dans la documentation de l’incident Checkmarx- Un fichier de verrouillage codé en dur,
/tmp/tmp.987654321.lock, empêche les exécutions simultanées - La charge utile est injectée dans
~/.bashrcet~/.zshrcafin d’assurer une persistance via le profil shell - Le dépôt est configuré avec la description
Shai-Hulud: The Third Coming, et des chaînes de debug comme"Would be executing butlerian jihad!"montrent un branding explicite
- Un fichier de verrouillage codé en dur,
- Même si les outils partagés suggèrent fortement un lien avec le même écosystème malveillant, la signature opérationnelle rend l’attribution plus difficile
- Après la découverte de l’attaque Checkmarx, TeamPCP a revendiqué l’opération via le compte social
@pcpcats - Le malware concerné tentait de se camoufler avec une description d’apparence légitime
- Après la découverte de l’attaque Checkmarx, TeamPCP a revendiqué l’opération via le compte social
- Cette charge utile adopte une posture publique différente
- Des marqueurs idéologiques sont directement intégrés dans le malware, comme les noms de dépôt Shai-Hulud, le manifeste
"Butlerian Jihad"et les messages de commit invoquant la résistance contre les machines - Plusieurs hypothèses restent ouvertes : un autre opérateur utilisant la même infrastructure, une faction plus idéologique, ou un changement de posture publique de la campagne
- Des marqueurs idéologiques sont directement intégrés dans le malware, comme les noms de dépôt Shai-Hulud, le manifeste
Recommandations
- Les organisations ayant installé le package npm malveillant de Bitwarden doivent traiter cet incident comme une exposition d’identifiants et une compromission CI/CD
- Il faut retirer immédiatement le package affecté des postes développeur et des environnements de build, puis remplacer tous les identifiants susceptibles d’y avoir été exposés
- Cela inclut les tokens GitHub, les tokens npm, les identifiants cloud, les clés SSH et les secrets CI/CD
- Sur GitHub, il faut rechercher les créations de dépôts non autorisées et les workflows anormaux
- Il faut vérifier les fichiers inattendus sous
.github/workflows/, les exécutions de workflows suspectes, les téléchargements d’artefacts et les dépôts publics suivant le motif de nommage inspiré de Dune{word}-{word}-{3digits} - En cas de compromission possible, il faut rechercher dans les dépôts récemment publiés les mots-clés suivants
atreidescogitorfedaykinfremenfutargesseritgholaharkonnenheighlinerkanlykralizeclasgunlazamelangementatnavigatorornithopterphibianpowindahpranaprescientsandwormsardaukarsayyadinasietchsiridarsligstillsuitthumpertleilaxu
- Il faut vérifier les fichiers inattendus sous
- Côté npm, il faut auditer toute publication non autorisée
- Il faut vérifier les publications non approuvées, les changements de version et les hooks d’installation nouvellement ajoutés
- Dans les environnements cloud, il faut réexaminer les logs d’accès
- Il est nécessaire de suivre les accès anormaux aux secrets, l’utilisation de tokens et les identifiants nouvellement émis
- Sur les endpoints et runners, il faut rechercher les traces de l’infrastructure d’exfiltration observée et des accès fichiers
- Il faut rechercher des connexions sortantes vers
audit[.]checkmarx[.]cx - Il faut vérifier s’il y a eu une exécution de Bun dans des environnements où ce n’est pas habituel
- Il faut examiner les traces d’accès à
.npmrc,.git-credentials,.env, aux stockages d’identifiants cloud, ainsi qu’àgcloud,azetazd - Il faut aussi vérifier la présence de
/tmp/tmp.987654321.locket toute modification de~/.bashrcet~/.zshrc
- Il faut rechercher des connexions sortantes vers
- Dans GitHub Actions, il faut vérifier s’il y a eu création de workflows non autorisés
- Il faut déterminer si des workflows ont été créés sur des branches temporaires
- Il faut aussi vérifier si des artefacts comme
format-results.txtont été créés ou téléchargés
- À plus long terme, il faut réduire le rayon d’impact des futurs incidents de chaîne d’approvisionnement
- Il faut réduire le périmètre des permissions des tokens et utiliser si possible des identifiants à courte durée de vie
- Il faut restreindre les droits de création et de publication de packages et durcir les permissions GitHub Actions
- Il faut désactiver l’accès inutile aux artefacts et surveiller les dépôts publics ou modifications de workflow apparus en dehors des procédures normales de release
Indicateurs de compromission
-
Package malveillant
-
Indicateurs réseau
94[.]154[.]172[.]43https://audit.checkmarx[.]cx/v1/telemetry
-
Indicateurs du système de fichiers
/tmp/tmp.987654321.lock/tmp/_tmp_<Unix Epoch Timestamp>/package-updated.tgz
1 commentaires
Commentaires sur Hacker News
Je me demande s’il existe une meilleure défense que d’imposer un délai d’attente minimal avant publication
Rien qu’en mettant
min-release-age=7dans.npmrc, les 334 personnes qui ont récupéré@bitwarden/cli 2026.4.0, publié il y a environ 19 heures avant d’être identifié comme malveillant, auraient sans doute pu l’éviterCela semble aussi assez bien fonctionner pour des cas comme
axios,ua-parser-jsounode-ipc, et même si ça ne bloque pas les cas où le code reste dormant longtemps commeevent-stream, ça paraît efficace contre la plupart des attaques aiguës sur la supply chainJ’ai mis des exemples de configuration pour ajouter un délai sur npm/pnpm/bun/uv, et comme il n’existait pas d’outil en un clic pour vérifier et appliquer ça, j’ai créé moi-même https://depsguard.com
Je viens aussi de voir https://cooldowns.dev, qui part d’une idée similaire
Il ne se contente pas d’imposer un âge minimal des releases : c’est un wrapper autour de npm/uv, etc., qui vérifie chaque dépendance avant installation contre une base de données commerciale de vulnérabilités afin de détecter des problèmes connus ou des signaux suspects
En pratique, il y a toujours quelqu’un qui met à jour tout de suite, mais on dirait que le processus même par lequel ces incidents sont révélés dépend en partie de ces utilisateurs qui mettent à jour très vite
Si vous devez impérativement récupérer tel quel le binaire du registre, un cooldown peut réduire un peu le risque
Pour les cas plus longs où GitHub lui-même a été infiltré, il faut sans doute une combinaison d’heuristiques sur les commits et les mainteneurs, d’analyse IA des changements de code, puis d’une revue humaine quand quelque chose paraît anormal
Pour info, je travaille là-dessus
Le point central de cet incident, c’est que le pipeline de build a été compromis, ce qui a permis de publier un package contaminé
Malgré tout, si vous mettez sur npm quelque chose d’important pour votre activité, mieux vaut vraiment épingler vos dépendances
Beaucoup de développeurs pensent qu’un lockfile suffit, mais s’il reste des plages
^, une mise à jour du lockfile peut faire remonter une nouvelle version que vous n’avez pas explicitement choisieSi le système en question peut affecter la survie de votre entreprise, cette contrainte supplémentaire en vaut la peine
https://github.com/doy/rbw est une alternative Rust au CLI Bitwarden
L’écosystème Rust donne lui aussi de plus en plus l’impression de devenir aussi vaste et profond que npm en matière d’arbre de dépendances, mais il y a tout de même bien moins d’auteurs à qui faire confiance que dans le cas typique du monde JavaScript
Au moins, les versions sont épinglées
rbw + vaultwardenfonctionne assez bien comme une version Rust auto-hébergeable de BitwardenOu alors vers des langages dont la bibliothèque standard embarque davantage de fonctionnalités
Mon expérience avec le CLI Bitwarden a été très mauvaise
J’ai lancé
bw listen pensant voir seulement les noms des mots de passe, mais il a en réalité affiché tous les mots de passe ainsi que les codes TOTP en coursLe plus inquiétant, c’est qu’en me connectant en ssh sur le serveur puis en ouvrant weechat dans tmux, tout le contenu de la commande
bwrestait accessible dans l’historique de saisie de weechatJe n’ai aucune idée de pourquoi, et cela persistait au-delà des sessions tmux et weechat ; il a fallu redémarrer le serveur pour que cela disparaisse
Après ça, j’ai désinstallé immédiatement le CLI
bwet je n’ai aucune intention de le réinstallerPour info, j’utilise ghostty comme terminal
Je me demande s’il existe une extension
bwclipour weechat, et j’ignorais même jusqu’ici que Bitwarden avait un CLIMoi j’utilise keepass en local
Je n’utilise pas le CLI, mais j’emploie le plugin navigateur
Si celui-ci se fait compromettre, ce serait vraiment catastrophique, et je ne sais pas quoi faire pour l’empêcher
Je me demande s’il faut continuer à utiliser une ancienne version vérifiée
C’est étrange de réaliser à quel point une grande partie de ma vie dépend du fait que ces secrets restent bien secrets
C’est pour ça que je n’utilise jamais les extensions navigateur pour les gestionnaires de mots de passe
Après avoir vu par le passé un produit avoir des problèmes de sécurité liés à l’intégration navigateur, je les évite complètement ; j’ai un peu plus confiance dans l’intégration iOS, mais je reste prudent
Cela inclut les gestionnaires de paquets pour le développement, ceux de l’OS, les extensions navigateur et même les mises à jour automatiques des applications autonomes
Il faut laisser à des sociétés comme Socket le temps de détecter une mise à jour malveillante ; si tout le monde télécharge quelques minutes après publication, cette détection perd tout son sens
Je recommande fortement cette configuration
Le titre m’a un peu fait sursauter, mais sans aller jusqu’à la paranoïa, j’ai le sentiment de faire tout ce qu’il est raisonnable de faire
https://cooldowns.dev
https://depsguard.com
Je maintiens le second, et si j’avais connu le premier plus tôt, je ne l’aurais probablement pas créé
Les deux font presque la même chose, même si le mien est un peu excessif parce qu’il est écrit en Rust
Le point le plus important ici, c’est qu’un simple
npm installsuffisaitSi le point de compromission est
preinstall, l’idée reçue selon laquelle on pourrait inspecter après installation s’effondre immédiatementÀ ce stade, le payload a déjà eu l’occasion de s’exécuter
C’est encore plus intéressant dans les environnements d’agents, de CI ou de sandbox éphémère : même si le temps d’exposition est court, une installation répétée automatiquement suffit pour se faire avoir
Un autre point notable, c’est que ce payload ne visait pas seulement les secrets, mais aussi la configuration des outils IA
La modification d’un profil shell pourrait de façon très réaliste devenir un vecteur de pollution du contexte lu par le prochain assistant de code
J’ai développé davantage cette idée avec le travail sur AgentSH ici : https://www.canyonroad.ai/blog/the-install-was-the-attack/
npm installcomme un problème à part est selon moi une thèse réfutée maintes foisDe toute façon, on finit par exécuter le vrai binaire
Et à vrai dire, si l’on veut être rigoureux, on peut aussi télécharger le package à l’avance et l’inspecter avant installation ; à moins de bien comprendre en profondeur les garanties et la portée de l’installateur, il est encore plus étrange de faire aveuglément confiance au processus qui télécharge et décompresse potentiellement du code malveillant
Un kill switch basé sur la locale russe, c’est à la fois audacieux et lâche
Discretion is the better part of valorEn gros, cela ressemble à une attitude du type on ne se tire pas dans le pied
Les fuites
Vault7mentionnaient déjà que la NSA et la CIA laissaient volontairement ce genre de traces pour brouiller l’attribution, et c’est une technique que d’autres acteurs étatiques peuvent très bien employer eux aussiCela ressemble trop à une trace trompeuse pour être honnête, tout en donnant fortement l’impression qu’un acteur étatique est impliqué
Vivre en utilisateur de KeePass est beaucoup moins stressant dans ce genre de situation
Rien que sur les cinq dernières années, utiliser KeePass dans mon infrastructure locale m’a permis d’éviter plusieurs incidents de sécurité
Ce n’est pas comme si ce genre de problème était impossible avec un outil d’accès pour KeePass non plus ; je ne vois donc pas très bien ce qui serait fondamentalement différent
J’ai toujours pensé que ce n’était pas possible, mais honnêtement je n’ai jamais creusé le sujet
Par exemple, si deux appareils hors ligne ajoutent chacun un mot de passe puis reviennent en ligne, comment cela se passe-t-il ?
Si l’on chiffre la sauvegarde, où stocke-t-on ce mot de passe ? Et où stocke-t-on alors le mot de passe du fournisseur cloud ?
Ce qui m’a particulièrement frappé dans cette attaque, c’est que les attaquants ont dû viser précisément un moment où GitHub n’était pas en panne
https://mrshu.github.io/github-statuses/
C’est pour ça que je n’utilise aucun gestionnaire de mots de passe tiers
Parce qu’il faut continuer à croire qu’ils vont correctement gérer la sécurité, les mises à jour, les sauvegardes, etc.
J’ai créé mon propre générateur de mots de passe stateless, ce qui supprime totalement le besoin de sauvegarder ou synchroniser des données entre appareils
Le principe est d’entrer un mot de passe maître très long et robuste, ainsi que le nom du service et le nom d’utilisateur, puis d’appliquer un hachage scrypt avec des paramètres appropriés pour rendre le brute force pratiquement impossible
Pour les comptes importants, j’utilise aussi la 2FA