ADEX a retracé une infection macOS active, d'un processus suspect à une menace plus large pesant sur la chaîne d'approvisionnement via les outils de développement Apple. L'affaire s'est concentrée sur XCSSET, une famille de malwares qui se dissimule dans les fichiers de projet Xcode plutôt que dans les applications finies, attendant qu'un développeur compile un projet pour déclencher la charge utile.
L'indice qui a lancé l'enquête

Le premier signe était discret mais étrange : une activité répétée de osascript s'exécutant depuis /tmp/jl. AppleScript est en soi un outil macOS ordinaire, mais l'emplacement avait son importance. Le répertoire /tmp est un espace temporaire, et non un endroit où un logiciel sain devrait relancer en permanence des scripts éphémères avec de grands arguments encodés.
ADEX a copié le fichier avant qu'il ne disparaisse. Une fois capturé, /tmp/jl s'est avéré être un AppleScript compilé. Son contenu était dissimulé sous plusieurs couches d'encodage base64, une méthode courante pour les malwares afin de cacher leur prochaine action à une inspection rapide.
Après décryptage, l'échantillon a révélé un script shell collectant des informations système. Il récupérait le nom d'utilisateur, les paramètres régionaux, la version de macOS, le type de CPU, l'état de la protection de l'intégrité du système, le numéro de série du Mac et des données liées à Chrome. Ces informations étaient envoyées vers riggletoy.ru, un domaine de commande et contrôle qu'ADEX a indiqué comme absent des flux de menaces publics à ce moment-là. Un second domaine, netcdndev.in – découvert plus tard lors de la phase d'investigation sur GitHub — était également absent de toute liste publique d'indicateurs de compromission.
Un fichier de build est devenu la porte d'entrée
Le danger de XCSSET vient de sa cachette. Les projets Xcode contiennent des fichiers project.pbxproj, qui indiquent au logiciel de développement d'Apple ce qu'il doit exécuter lors d'une compilation. Un script malveillant placé à cet endroit peut s'exécuter sous le propre compte du développeur lorsque le projet est compilé.
Cela rend l'attaque discrète. Aucun installateur suspect n'est nécessaire. Aucune icône d'application évidente n'apparaît. Un développeur peut cloner un projet depuis GitHub, l'ouvrir dans Xcode, appuyer sur Build, et offrir au malware le moment dont il a besoin.
L'infection recherche ensuite d'autres projets Xcode sur la machine. ADEX a trouvé plus de 20 projets altérés sur le poste de travail affecté, tous modifiés dans la même minute. Ce timing indiquait un balayage automatisé, et non une modification humaine. Un poste de travail infecté était déjà devenu un point de départ pour une propagation ultérieure.
La persistance était le véritable problème
Nettoyer un seul projet ne suffirait pas à résoudre le cas. ADEX a trouvé un faux Launchpad.app enfoui dans un dossier de cache utilisateur, tandis que le vrai Launchpad se trouve dans /System/Applications/Launchpad.app. Ce détail correspondait à une « méthode dock » connue, où le malware redirige une icône du Dock afin qu'un utilisateur ouvre à la fois l'application réelle et la charge utile cachée sans s'en apercevoir.
Le rapport décrivait des mécanismes de persistance supplémentaires, notamment des agents de lancement, des modifications du profil shell et des hooks git. La leçon était claire : les projets infectés n'étaient que des symptômes. Le mécanisme maintenant l'infection en vie devait être supprimé en premier.
La procédure de nettoyage d'ADEX était stricte. Supprimer les points de démarrage automatique, redémarrer, puis restaurer les projets Xcode depuis un état git propre. Inverser cet ordre risquait de laisser le malware réécrire les fichiers nettoyés.
GitHub a révélé une piste plus large
L'enquête s'est étendue d'une seule machine à des dépôts publics. ADEX a signalé 24 dépôts GitHub contenant des chaînes de charge utile XCSSET. Parmi les exemples figuraient PrinceMittal1/DemoForAuthFlow, zzzznick/dummy-ios et dvillegastech/ReaxBD.
Un dépôt, usamajaved357/Breezy, utilisait riggletoy.ru, le même domaine observé dans l'échantillon actif. Un autre, xiaoyouPrince/XYDevTool, utilisait netcdndev.In, un domaine qu'ADEX a décrit comme absent de la liste publique des indicateurs de compromission au moment de l'inspection, indiquant que les opérateurs font tourner leur infrastructure plus rapidement que les flux de menaces publics ne peuvent le suivre. Douze des 24 dépôts ont reçu des commits en 2026, le plus récent datant d'un jour avant l'inspection – plusieurs dépôts présentaient une activité en 2026, suggérant que la campagne se propageait encore via du code partagé.
Ces chiffres sont importants car la confiance des développeurs fait partie du vecteur d'attaque. Les fichiers de projet Xcode sont souvent traités comme une infrastructure de routine, moins visibles que le code source ou les dépendances. XCSSET exploite cette habitude.
Le risque pour les développeurs Apple
La cible directe n'est pas l'utilisateur de l'App Store. La cible est la personne qui développe des logiciels, ainsi que les identifiants, sessions de navigateur, dépôts et tokens stockés sur cette machine.
XCSSET peut extraire des données depuis les navigateurs, le Keychain et les fichiers de configuration — y compris les clés cloud, les tokens AWS, les clés SSH et les identifiants Git — remplacer les adresses de portefeuilles Bitcoin ou Ethereum copiées, et modifier le comportement du navigateur via du code JavaScript injecté. Pour une équipe logicielle, cela signifie qu'un Mac compromis peut mettre en danger le code source, les comptes et les projets en aval.
La défense pratique commence avant d'appuyer sur le bouton de compilation. Les développeurs doivent inspecter les phases de build Xcode inconnues et maintenir les fichiers project.pbxproj sous contrôle de version, surveiller les hooks git globaux, maintenir la protection de l'intégrité du système activée et surveiller le trafic sortant inattendu. Les équipes de sécurité doivent traiter les ordinateurs portables des développeurs comme faisant partie de la chaîne d'approvisionnement, et non comme des endpoints ordinaires.








