Aller au contenu
medium

Checkmarx/KICS compromis : quand les scanners de sécurité deviennent la surface d'attaque

23 min de lecture

Après Trivy, je pensais que le message était clair : un outil de sécurité compromis n’est pas une vulnérabilité comme les autres.

Avec Checkmarx/KICS, le message devient encore plus brutal.

Nous ne parlons plus seulement d’un outil qui contient une faille. Nous parlons d’un outil de sécurité que des équipes exécutent volontairement dans leurs pipelines CI/CD, sur leurs dépôts, sur leurs fichiers Terraform et Kubernetes, parfois avec des variables d’environnement sensibles à portée de main.

Autrement dit, un scanner de sécurité compromis peut devenir un excellent point d’observation pour un attaquant. Et c’est précisément ce que cette nouvelle vague autour de Checkmarx/KICS vient rappeler.

Ce qui s’est passé

Le 22 avril 2026, Checkmarx a publié une mise à jour de sécurité concernant un incident supply chain en cours d’investigation.

Les artefacts potentiellement affectés incluent notamment :

  • l’image Docker publique checkmarx/kics ;
  • l’action GitHub checkmarx/ast-github-action ;
  • l’extension VS Code Checkmarx AST Results ;
  • l’extension Checkmarx Developer Assist.

Checkmarx indique que les artefacts malveillants n’auraient pas remplacé des versions connues comme sûres publiées avant les fenêtres d’exposition identifiées. Le risque dépend donc fortement du moment où les artefacts ont été téléchargés, exécutés ou mis en cache.

Mais c’est aussi ce qui rend l’incident difficile à gérer opérationnellement. Dans beaucoup d’environnements CI/CD, on ne sait pas toujours précisément quel tag a été tiré, à quel moment, sur quel runner, avec quel digest réel, depuis quel cache, avec quels secrets accessibles et avec quelle connectivité sortante.

C’est là que le sujet dépasse largement Checkmarx.

Les artefacts concernés

D’après le bulletin Checkmarx du 22 avril, l’image Docker publique checkmarx/kics a été exposée sur une fenêtre très courte, entre le 22 avril 2026 12:31:35 UTC et 12:59:46 UTC.

Les tags malveillants listés incluent notamment :

latest
alpine
debian
v2.1.20
v2.1.21
v2.1.20-debian
v2.1.21-debian

L’action GitHub checkmarx/ast-github-action est également mentionnée, avec le tag 2.3.35, sur une fenêtre allant du 22 avril 2026 14:17:59 UTC à 15:41:31 UTC.

Checkmarx liste aussi deux familles d’extensions :

  • Checkmarx VS Code extension : versions 2.63 et 2.66 ;
  • Checkmarx Developer Assist extension : versions 1.17 et 1.19.

Pour les extensions, les fenêtres exactes restent à confirmer au moment où j’écris.

Pourquoi KICS est une cible intéressante

KICS n’est pas un outil anodin. C’est un scanner IaC. Il analyse des fichiers Terraform, Kubernetes, CloudFormation et d’autres configurations d’infrastructure.

Il peut donc voir des éléments que beaucoup d’équipes considèrent comme « pas vraiment secrets », mais qui sont très utiles pour un attaquant : noms de ressources cloud, noms de comptes, régions, chemins internes, conventions de nommage, topologie réseau, buckets, clusters, endpoints, variables, secrets mal placés, tokens oubliés, clés exposées dans des fichiers de test.

Le problème n’est pas seulement qu’un scanner puisse détecter des erreurs. Le problème est qu’un scanner compromis peut lire exactement les mêmes données que le scanner légitime, puis les exfiltrer.

C’est une inversion complète de la promesse de sécurité.

Le pattern ressemble à Trivy

Dans mon analyse de l’affaire Trivy, un point me semblait déjà central : l’attaquant n’avait pas seulement compromis un dépôt, il avait touché un maillon de confiance utilisé automatiquement par les équipes.

Avec Trivy, l’histoire a commencé par un workflow GitHub Actions mal maîtrisé, un token privilégié, puis une compromission qui a touché les releases, les tags et plusieurs canaux de distribution.

Avec KICS/Checkmarx, Docker indique qu’un acteur malveillant s’est authentifié sur Docker Hub avec des identifiants éditeur Checkmarx valides, puis a poussé des images malveillantes sur le dépôt checkmarx/kics.

Ce point est essentiel. L’attaque ne consiste pas à publier un faux outil nommé presque pareil. Elle consiste à passer par un canal officiel, avec des identifiants valides, sur un dépôt que les équipes peuvent déjà utiliser en production.

C’est ce qui rend ces incidents si dangereux.

Le binaire continue de fonctionner

Autre détail important : d’après Docker, le binaire KICS empoisonné conservait la surface de scan légitime.

C’est un comportement classique dans les attaques supply chain sérieuses. L’outil continue de faire ce que l’utilisateur attend de lui. Il scanne. Il produit une sortie. Il semble fonctionner. Mais il ajoute en parallèle une voie discrète d’exfiltration.

Dans le cas documenté par Docker, les données de scan étaient collectées, chiffrées puis envoyées vers une infrastructure contrôlée par l’attaquant, notamment via audit.checkmarx[.]cx, avec l’User-Agent KICS-Telemetry/2.0.

C’est exactement pour cette raison qu’il ne faut pas se contenter d’une vérification du type « le job CI est passé, donc tout va bien ». Un outil compromis peut très bien fonctionner correctement tout en faisant autre chose.

La compromission se propage en aval : Bitwarden CLI

Deux jours après le bulletin Checkmarx, un nouveau volet s’ajoute : Bitwarden CLI, le client en ligne de commande du gestionnaire de mots de passe Bitwarden, a été compromis via le même vecteur.

Ce que Bitwarden confirme

Dans son communiqué, Bitwarden indique qu’un package npm malveillant a été distribué sur une fenêtre courte :

  • package : @bitwarden/cli@2026.4.0 (la version saine au moment des faits était 2026.3.0) ;
  • fenêtre officielle : entre le 22 avril 2026 17:57 ET et 19:30 ET ;
  • SafeDep précise que la release npm malveillante a été publiée à 21:22:59 UTC le 22 avril ;
  • deux fichiers malveillants : un loader bw_setup.js et un payload bw1.js, déclenchés par un hook preinstall dans le package.json ("preinstall": "node bw_setup.js") ;
  • cause racine : le dépôt GitHub de Bitwarden utilisait checkmarx/ast-github-action, compromis lors de l’incident Checkmarx.

Bitwarden précise qu’aucune donnée de coffre utilisateur n’a été accédée, que la release npm a été dépréciée, que les accès compromis ont été révoqués, et qu’un CVE est en cours d’émission pour cette version de la CLI.

Pourquoi ce volet change la nature de l’incident

Ce n’est plus seulement Checkmarx qui est compromis. C’est un consommateur de l’action GitHub Checkmarx qui se retrouve à son tour distributeur de code malveillant, dans un package largement adopté côté postes développeurs.

Autrement dit, la compromission se propage en aval, via les dépôts qui utilisaient l’action checkmarx/ast-github-action dans leur pipeline de publication. StepSecurity résume bien le risque :

A single developer with @bitwarden/cli@2026.4.0 installed can become the entry point for a broader supply chain compromise.

Ce que fait le payload bw1.js

D’après JFrog, Socket, StepSecurity, Endor Labs, GitGuardian, SafeDep et OX Security, le code malveillant enchaîne plusieurs capacités :

  • vol de secrets : tokens GitHub (pattern ghp_) et npm (pattern npm_), .ssh, .env, historique shell, secrets GitHub Actions, credentials cloud ;
  • ciblage des assistants IA : configurations locales de Claude Code (~/.claude.json), Cursor, Kiro (~/.kiro/settings/mcp.json), Codex CLI, Aider, Gemini CLI et OpenCode ;
  • exfiltration chiffrée : données compressées en gzip, chiffrées en AES-256-GCM puis encapsulées avec RSA OAEP, envoyées à audit.checkmarx[.]cx (le même domaine que KICS, IP 94.154.172.43) ;
  • canal de repli Cloudflare : GitGuardian a identifié un tunnel secondaire via safely-irc-weblogs-few[.]trycloudflare[.]com ;
  • fallback par GitHub : création de dépôts publics sous le compte de la victime (schéma observé helloworm00/hello-world, helloworm00/my-first-repo), avec récupération de PAT stagés dans des commits publics marqués LongLiveTheResistanceAgainstMachines et découverte de domaines d’exfiltration via des commits signés beautifulcastle ;
  • worm npm auto-propageant : avec un token npm volé, le malware republie automatiquement des versions malveillantes des autres packages que la victime peut publier ;
  • injection de workflow GitHub Actions : avec un token GitHub volé, le malware ajoute un workflow malveillant qui capture les secrets accessibles dans les dépôts concernés.

OX Security relève une chaîne Shai-Hulud: The Third Coming dans le package, qui suggère une filiation avec la campagne Shai-Hulud déjà connue. Socket note par ailleurs que le malware s’arrête s’il détecte une locale russe, signature opérationnelle intéressante pour le threat hunting.

Le chercheur Adnan Khan souligne un autre point inédit : ce serait la première compromission documentée d’un package publié via NPM trusted publishing. SafeDep nuance en rappelant que « trusted publishing réduit une classe de vol de tokens, mais ne sauve pas une pipeline de release qu’un workflow empoisonné peut toujours piloter ».

IOC spécifiques Bitwarden

Package npm : @bitwarden/cli@2026.4.0
Loader : bw_setup.js
Payload : bw1.js
Hook : preinstall (node bw_setup.js)
SHA-256 loader : 18f784b3bc9a0bcdcb1a8d7f51bc5f54323fc40cbd874119354ab609bef6e4cb
SHA-256 payload : 8605e365edf11160aad517c7d79a3b26b62290e5072ef97b102a01ddbb343f14
Domaines / C2 : audit.checkmarx[.]cx
safely-irc-weblogs-few[.]trycloudflare[.]com
IP : 94.154.172.43
Signatures : Shai-Hulud: The Third Coming
LongLiveTheResistanceAgainstMachines
beautifulcastle
Comptes fallback : helloworm00/hello-world, helloworm00/my-first-repo

Les IOC réseau partagés avec KICS (audit.checkmarx[.]cx, User-Agent KICS-Telemetry/2.0) restent pertinents.

Si un poste a installé la version 2026.4.0 pendant la fenêtre

La réponse à incident doit aller plus loin qu’une simple désinstallation :

  • considérer tous les secrets du poste comme compromis : tokens GitHub, tokens npm, clés SSH, credentials cloud, variables .env, historique shell ;
  • inspecter les dépôts publics récemment créés sous le compte GitHub du développeur pour repérer un dépôt au schéma <mot>-<mot>-<3 chiffres> ;
  • auditer les workflows GitHub Actions récemment ajoutés dans tous les dépôts accessibles avec le token du développeur ;
  • auditer les packages npm publiés récemment si un token npm avec droits de publication était présent sur la machine, à cause du comportement de worm ;
  • vérifier les configurations locales des assistants IA : Claude, Cursor, Aider, Codex CLI, Kiro.

Les indicateurs à surveiller

Les indicateurs communiqués publiquement permettent au minimum de lancer une première vérification.

Domaines et IP à bloquer ou rechercher dans les logs :

checkmarx.cx
audit.checkmarx.cx
91.195.240.123
94.154.172.43

User-Agent à rechercher :

KICS-Telemetry/2.0

Exemples de recherches simples dans des logs proxy ou egress :

Fenêtre de terminal
grep -R "audit.checkmarx" /var/log 2>/dev/null
grep -R "checkmarx.cx" /var/log 2>/dev/null
grep -R "KICS-Telemetry/2.0" /var/log 2>/dev/null

Dans un environnement centralisé, l’idée est de chercher les connexions sortantes vers les domaines mentionnés, les résolutions DNS, les connexions HTTP(S) suspectes depuis des runners CI, les traces d’exécution de KICS pendant la fenêtre d’exposition, les digests Docker réellement tirés et les caches locaux ou intermédiaires qui auraient pu conserver l’image.

Le piège des tags Docker

Cet incident rappelle une règle simple : un tag Docker n’est pas une garantie d’intégrité.

latest n’est pas une version. v2.1.20 n’est pas une preuve cryptographique. Un tag peut être déplacé, réécrit ou repointer temporairement vers un digest malveillant. Le seul identifiant exploitable pour une politique stricte est le digest.

Mauvais exemple :

image: checkmarx/kics:latest

Mieux :

image: checkmarx/kics@sha256:<digest-attendu>

Même logique côté GitHub Actions.

Mauvais exemple :

uses: checkmarx/ast-github-action@2.3.35

Mieux :

uses: checkmarx/ast-github-action@<commit-sha>

Cela ne supprime pas tous les risques, mais cela évite au moins qu’un tag mutable modifie silencieusement ce qui est exécuté.

Le vrai sujet : ce que le scanner peut voir

La question opérationnelle n’est pas seulement « est-ce que j’ai utilisé Checkmarx ou KICS ? ». La vraie question est « qu’est-ce que ce scanner pouvait voir au moment où il s’est exécuté ? ».

Dans une pipeline CI/CD, cela peut inclure le contenu complet du dépôt, les variables d’environnement, des tokens CI/CD, un token GitHub ou GitLab, des credentials cloud temporaires, des fichiers de configuration, des clés SSH, des fichiers .npmrc, .pypirc, .docker/config.json, des manifests Kubernetes, des plans Terraform et des sorties de scan contenant des chemins, ressources ou secrets.

C’est pour cela que la rotation doit être guidée par l’exposition réelle, pas seulement par le nom de l’outil.

Si le scanner a tourné dans un job sans secret, sans credentials cloud, sans réseau sortant et sur un dépôt public sans donnée sensible, le niveau de risque n’est pas le même. S’il a tourné dans un runner partagé, avec accès aux variables CI/CD, aux credentials cloud et à Internet, la situation est complètement différente.

Ce que je vérifierais immédiatement

Voici la checklist minimale que j’appliquerais après ce type d’incident.

1. Identifier les usages

Chercher les références à Checkmarx, KICS et aux actions associées :

Fenêtre de terminal
grep -R "checkmarx/kics\|checkmarx/ast-github-action\|kics" .github .gitlab-ci.yml . 2>/dev/null

Dans GitLab CI, regarder aussi les includes, templates internes et composants partagés. Dans GitHub Actions, vérifier les workflows, actions composites et workflows réutilisables.

2. Identifier les digests réellement tirés

Sur les runners ou machines de build encore accessibles :

Fenêtre de terminal
docker image ls --digests | grep -i checkmarx

Si un registry mirror, un proxy ou un cache interne est utilisé, il faut aussi vérifier ce niveau-là. Un tag restauré côté Docker Hub ne purge pas automatiquement vos caches.

3. Purger les caches

Selon l’architecture, il faut passer en revue les caches Docker locaux, les caches GitLab Runner, les caches GitHub self-hosted runners, les registry mirrors, les pull-through caches, les artefacts CI, les caches de dépendances et les images répliquées dans un registre interne.

Un simple nouveau docker pull ne suffit pas si un digest malveillant est déjà présent localement.

4. Chercher les IOC réseau

Rechercher les domaines, IP et User-Agent communiqués. À minima :

checkmarx.cx
audit.checkmarx.cx
91.195.240.123
94.154.172.43
KICS-Telemetry/2.0

5. Renouveler les secrets exposés

La rotation ne doit pas être symbolique. Il faut partir de la question suivante : quels secrets étaient accessibles au job ou au poste qui a exécuté l’artefact compromis ?

À considérer : tokens GitHub ou GitLab, clés SSH, credentials AWS, Azure, Google Cloud, tokens npm, tokens Docker Hub, secrets Kubernetes, variables CI/CD, credentials Terraform, secrets présents dans les fichiers IaC, tokens d’agents IA ou de configurations MCP si présents sur le poste développeur.

6. Revoir les extensions IDE

C’est un point encore trop peu traité dans les politiques DevSecOps.

Une extension VS Code n’est pas un simple confort développeur. Elle s’exécute dans un environnement riche : accès au workspace, accès potentiel aux fichiers de configuration, accès aux variables locales, accès aux tokens stockés, accès aux clés et credentials selon la configuration du poste, possibilité de télécharger du code additionnel.

Les extensions doivent être traitées comme des dépendances logicielles, pas comme des préférences personnelles invisibles.

Ce que cet incident dit de nos pipelines

Le vrai problème n’est pas Checkmarx. Le vrai problème, c’est notre modèle de confiance.

Nous avons construit des pipelines qui téléchargent et exécutent automatiquement des images Docker, des GitHub Actions, des scripts d’installation, des extensions, des packages, des scanners, des helpers, des wrappers et des agents. Puis nous avons ajouté des secrets dans ces mêmes environnements parce qu’il fallait bien déployer, scanner, publier, signer, pousser, notifier, créer des releases et accéder au cloud.

Et maintenant nous découvrons que les attaquants visent précisément ces chemins de confiance. Ils n’ont plus besoin de compromettre directement l’application. Ils compromettent l’outil qui regarde l’application. Ils compromettent l’outil qui scanne l’infrastructure. Ils compromettent l’outil que nous avons placé dans la pipeline au nom de la sécurité.

Mes recommandations après Trivy et Checkmarx

Je ne crois pas que la bonne réponse soit de bannir l’open source ou d’arrêter d’utiliser des scanners. Ce serait irréaliste et probablement contre-productif. En revanche, il faut changer de posture.

1. Confiner les scanners

Un scanner ne doit pas avoir accès par défaut à tous les secrets de la pipeline. Il faut séparer les jobs : scan sans secret, build sans credentials de production, déploiement avec credentials limités, publication avec permissions minimales.

Un scanner IaC n’a pas besoin d’un token cloud administrateur pour lire des fichiers Terraform.

Exemple GitLab CI : scanner sans secrets

Le confinement commence par une règle simple : le job de scan ne doit pas hériter des secrets nécessaires au déploiement.

Mauvais modèle :

variables:
AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
kics_scan:
image: checkmarx/kics:latest
script:
- kics scan -p .

Dans cet exemple, le scanner utilise un tag mutable et s’exécute dans un contexte où des credentials cloud peuvent être disponibles.

Meilleur modèle :

kics_scan:
image: checkmarx/kics@sha256:<digest-valide-et-verifie>
stage: test
script:
- kics scan -p .
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

Les credentials cloud, les tokens de publication et les secrets de déploiement doivent rester dans des jobs séparés, protégés, et uniquement disponibles quand ils sont réellement nécessaires.

2. Réduire l’egress

Un runner CI qui peut sortir librement vers Internet est un excellent canal d’exfiltration. Le filtrage réseau ne doit pas être décoratif.

Il faut pouvoir dire quels domaines sont autorisés, quels flux sortants sont normaux, quels jobs ont le droit d’accéder à Internet et quels jobs doivent être isolés.

3. Épingler les dépendances exécutables

Pour les images, viser image@sha256:<digest>. Pour les GitHub Actions, viser owner/repo@<commit-sha>. Pour les packages, s’appuyer sur des lockfiles, une vérification d’intégrité, un registre interne, une politique de promotion et un délai avant adoption automatique.

4. Surveiller les comportements

La réputation d’un projet ne suffit plus. Il faut surveiller les connexions sortantes inhabituelles, les User-Agents inattendus, les nouveaux domaines, les changements de provenance, les tags sans release upstream, les images construites depuis une source inattendue et les variations brutales de digest.

Docker explique justement que la détection est venue d’une corrélation de signaux : nouveau tag, provenance inhabituelle, absence de release upstream et comportement de publication anormal.

5. Ne pas faire confiance aux caches

Les caches accélèrent les builds. Ils accélèrent aussi la persistance d’un artefact compromis.

Après un incident de ce type, il faut vérifier et purger les runners, les registres internes, les mirrors, les caches de dépendances, les postes développeurs et les environnements de test.

6. Documenter la réponse à incident CI/CD

La question n’est pas de savoir si un autre outil sera compromis. La question est de savoir si votre équipe saura répondre vite.

Il faut donc préparer une procédure d’inventaire des workflows, de recherche des artefacts, de rotation des secrets, de purge des caches, d’analyse egress, de désactivation temporaire des outils compromis, ainsi qu’une liste de contacts internes et de sources de confiance à suivre.

Ce que je change dans ma lecture des outils DevSecOps

Après Trivy, j’avais déjà changé mon niveau d’exigence. Après Checkmarx/KICS, je vais encore plus loin : un outil DevSecOps doit être traité comme une dépendance critique de production.

Pas parce que l’éditeur est mauvais. Pas parce que l’open source serait dangereux par nature. Mais parce que ces outils sont placés à des endroits extrêmement sensibles : au cœur des pipelines, au contact du code, au contact des secrets, au contact de l’infrastructure et au contact des postes développeurs.

Le scanner n’est pas extérieur au système. Il fait partie du système. Et quand il est compromis, il hérite de la confiance que nous lui avons donnée.

À retenir

  • L’incident Checkmarx/KICS touche simultanément l’image Docker officielle, l’action GitHub et deux extensions IDE : c’est une surface hybride, pas un simple « package compromis ».
  • Le binaire KICS empoisonné conservait la fonction de scan légitime tout en exfiltrant vers audit.checkmarx[.]cx avec l’User-Agent KICS-Telemetry/2.0.
  • La compromission est passée par des identifiants éditeur valides sur Docker Hub, pas par du typosquat : le canal officiel lui-même a été utilisé.
  • Un tag Docker ou GitHub Action n’est pas une garantie d’intégrité. Seul le digest ou le SHA de commit l’est.
  • La rotation doit suivre l’exposition réelle du job : quels secrets étaient visibles par le scanner au moment où il s’est exécuté ?
  • Les extensions IDE sont des dépendances logicielles, pas des préférences personnelles. Elles doivent entrer dans la politique de dépendances.
  • Après Trivy puis Checkmarx/KICS, il faut confiner les scanners : moins de secrets, moins d’egress, pinning strict, détection comportementale, pas de confiance aveugle dans les caches.
  • La compromission s’est propagée en aval via checkmarx/ast-github-action jusqu’à Bitwarden CLI (@bitwarden/cli@2026.4.0, loader bw_setup.js, hook preinstall) : un consommateur de l’action a été transformé en distributeur de malware ciblant notamment les configurations d’assistants IA (Claude Code, Cursor, Kiro, Aider, Codex CLI, Gemini CLI, OpenCode).

Conclusion

Trivy nous avait déjà envoyé un signal très fort. Checkmarx/KICS confirme que ce n’était pas une anomalie. Et l’extension Bitwarden CLI démontre que la compromission d’un scanner devient très vite la compromission de tout projet qui consomme ce scanner.

Les attaquants visent désormais les outils que nous utilisons pour sécuriser nos chaînes de livraison, puis les produits que ces outils contribuent à publier. C’est logique : ces outils sont installés partout, exécutés automatiquement et rarement confinés correctement.

Le DevSecOps ne peut donc plus se résumer à ajouter un scanner dans une pipeline. Il faut aussi sécuriser le scanner : son mode d’exécution, ses permissions, son réseau, ses mises à jour, ses caches et les secrets qu’il peut voir. Sinon, nous ne faisons qu’ajouter une nouvelle porte d’entrée au nom de la sécurité.

Sources

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn