1 points par GN⁺ 7 일 전 | 1 commentaires | Partager sur WhatsApp
  • 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/cli 2026.4.0
  • Le code malveillant bw1.js inclus dans le package utilise la même infrastructure et les mêmes techniques d’obfuscation, comme audit.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 ~/.bashrc et ~/.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
  • À 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.js partage l’infrastructure centrale du mcpAddon.js de Checkmarx analysé la veille
    • Elle utilise le même endpoint C2 audit.checkmarx[.]cx/v1/telemetry et est obfusquée avec __decodeScrambled et la graine 0x3039
    • Elle exfiltre aussi via des commits passant par l’API GitHub et vole des tokens npm pour redistribution via le registre npm
  • 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.Worker dans GitHub Actions pour viser les tokens GitHub
    • Un loader setup.mjs pour 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
  • 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.Worker et 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 via gcloud config config-helper
    • .npmrc, les clés SSH, les variables d’environnement et les fichiers de configuration Claude/MCP font aussi partie des cibles
  • 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 LongLiveTheResistanceAgainstMachines ainsi que le token
  • 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 preinstall injecté
    • Il injecte aussi des workflows GitHub Actions pour collecter davantage de secrets de dépôt
  • 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().locale ainsi que les variables d’environnement LC_ALL, LC_MESSAGES, LANGUAGE et LANG
  • L’environnement d’exécution est Bun v1.3.13, téléchargé depuis GitHub Releases

Différences par rapport à l’incident Checkmarx

  • bw1.js contient 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 ~/.bashrc et ~/.zshrc afin 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
  • 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
  • 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

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
      • atreides
      • cogitor
      • fedaykin
      • fremen
      • futar
      • gesserit
      • ghola
      • harkonnen
      • heighliner
      • kanly
      • kralizec
      • lasgun
      • laza
      • melange
      • mentat
      • navigator
      • ornithopter
      • phibian
      • powindah
      • prana
      • prescient
      • sandworm
      • sardaukar
      • sayyadina
      • sietch
      • siridar
      • slig
      • stillsuit
      • thumper
      • tleilaxu
  • 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, az et azd
    • Il faut aussi vérifier la présence de /tmp/tmp.987654321.lock et toute modification de ~/.bashrc et ~/.zshrc
  • 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.txt ont é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

1 commentaires

 
GN⁺ 7 일 전
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=7 dans .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’éviter
    Cela semble aussi assez bien fonctionner pour des cas comme axios, ua-parser-js ou node-ipc, et même si ça ne bloque pas les cas où le code reste dormant longtemps comme event-stream, ça paraît efficace contre la plupart des attaques aiguës sur la supply chain
    J’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

    • J’utilise Aikido safe-chain
      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
    • L’idée du cooldown est bonne, mais je me demande aussi si cette attaque aurait réellement été détectée si personne n’avait mis à jour immédiatement
      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
    • Je pense qu’il vaut mieux commencer par ne pas mettre de backend ni d’outils CLI sur NPM
    • Pour une nouvelle installation, soit, mais pour les dépendances existantes, il ne suffirait pas de figer la version patch et de fixer le sha ?
    • Ces attaques ne remontent généralement pas jusqu’à la source upstream, donc une approche comme celle de https://www.chainguard.dev/libraries, qui compile depuis les sources, en bloquerait à peu près 98 %
      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 choisie
    Si le système en question peut affecter la survie de votre entreprise, cette contrainte supplémentaire en vaut la peine

    • En sens inverse, on peut aussi dire qu’idéalement, quand une faille de sécurité est corrigée dans une version ultérieure, le système devrait pouvoir l’adopter automatiquement
  • 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

    • Si on regarde https://github.com/doy/rbw/blob/main/Cargo.toml#L16, on voit qu’ici aussi il y a pas mal de dépendances
      Au moins, les versions sont épinglées
    • Je me demande s’il y a des inconvénients à utiliser le gestionnaire de mots de passe intégré à Firefox
    • On dirait que tout le monde considère Rust comme plus sûr, tout en minimisant beaucoup trop facilement le risque de récupérer un malware via les dépendances
    • La combinaison rbw + vaultwarden fonctionne assez bien comme une version Rust auto-hébergeable de Bitwarden
    • Des événements comme celui-ci pourraient pousser davantage de logiciels vers des stacks comme .Net, où l’on peut résoudre la plupart des besoins sans dépendances tierces
      Ou 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 list en 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 cours
    Le 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 bw restait accessible dans l’historique de saisie de weechat
    Je 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 bw et je n’ai aucune intention de le réinstaller
    Pour info, j’utilise ghostty comme terminal

    • Cela ressemble davantage à une plainte sans rapport avec le sujet principal
    • J’avais voulu essayer le CLI, puis j’ai vu qu’il était basé sur JavaScript et j’ai laissé tomber
    • C’est vraiment étrange
      Je me demande s’il existe une extension bwcli pour weechat, et j’ignorais même jusqu’ici que Bitwarden avait un CLI
      Moi 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

    • Plus il y a de points d’intégration, plus la surface d’attaque s’agrandit
      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
    • Les cooldowns devraient être activés par défaut partout
      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
    • Mes actifs numériques les plus précieux, à savoir mon e-mail et mon compte Bitwarden, sont protégés en permanence par une Yubikey que je garde sur moi et une clé de secours conservée dans un autre lieu
      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
    • Au lieu du plugin navigateur, on peut simplement utiliser l’application desktop ou le web vault directement
    • Pour se protéger, en gros, cela tient à ces deux liens
      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 install suffisait
    Si 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/

    • En pratique, personne n’inspecte les packages après installation, et considérer spécifiquement les scripts npm install comme un problème à part est selon moi une thèse réfutée maintes fois
      De 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

    • Le pire, c’est qu’on ne peut même pas savoir si c’est une vraie piste ou un false flag
    • Ça fait penser à toutes sortes d’adages, comme Discretion is the better part of valor
      En gros, cela ressemble à une attitude du type on ne se tire pas dans le pied
    • En soi, ce n’est pas une preuve décisive
      Les fuites Vault7 mentionnaient 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 aussi
    • On dirait aussi une opération d’intimidation menée par un autre pays
    • Qui configurerait une locale de cette manière dans une tâche GitHub CI de publication npm ?
      Cela 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é

    • Ici, le problème ne concernait pas le coffre-fort lui-même, mais l’outil d’accès
      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 besoin d’accéder à mes mots de passe depuis mon infrastructure et mon téléphone, et je me demande comment on résout ça avec KeePass
      J’ai toujours pensé que ce n’était pas possible, mais honnêtement je n’ai jamais creusé le sujet
    • C’est très bien pour les personnes capables de gérer leur propre infrastructure, mais il est difficile d’étendre l’idée de stress free à l’utilisateur moyen
    • Je comprends le principe du fichier unique, mais en pratique je me demande comment on gère la synchronisation et les conflits
      Par exemple, si deux appareils hors ligne ajoutent chacun un mot de passe puis reviennent en ligne, comment cela se passe-t-il ?
    • Ce que je n’arrive pas encore à cerner avec KeePass, c’est la question de la sauvegarde cloud
      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

  • 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