On June 1, 2026, security researchers at Microsoft, Snyk, Wiz, and Orca Security simultaneously flagged malicious code embedded in 32 npm package releases published under the @redhat-cloud-services namespace — the set of frontend components and API clients that powers the Red Hat Hybrid Cloud Console. The attacker gained access by compromising a Red Hat employee’s GitHub account, then pushed orphan commits directly into two RedHatInsights repositories, bypassing code review. The real innovation: the malicious workflow leveraged GitHub Actions OIDC tokens to publish backdoored packages carrying valid SLSA provenance attestations, making them appear completely legitimate to every automated security scanner. The payload — named Miasma: The Spreading Blight by the attacker — is the latest variant of the Shai-Hulud self-propagating worm family. It harvests SSH keys, cloud credentials, CI/CD secrets, and Kubernetes tokens, then republishes poisoned packages to spread further. This article covers the full attack chain, the new Phantom Gyp bypass technique, and a practical hardening guide.

Le 1er juin 2026, des chercheurs en sécurité de Microsoft, Snyk, Wiz et Orca Security ont simultanément détecté du code malveillant dans 32 versions de packages npm publiées sous le namespace @redhat-cloud-services — l’ensemble des composants frontend et clients API qui propulse la Red Hat Hybrid Cloud Console. L’attaquant a obtenu l’accès en compromettant le compte GitHub d’un employé Red Hat, puis a pusé des commits orphelins directement dans deux dépôts RedHatInsights, contournant la revue de code. L’innovation réelle : le workflow malveillant a exploité des tokens OIDC GitHub Actions pour publier des packages backdoorés portant des attestations de provenance SLSA valides, les rendant totalement légitimes aux yeux de chaque scanner de sécurité automatisé. Le payload — nommé Miasma : The Spreading Blight par l’attaquant — est la dernière variante de la famille de vers auto-propagants Shai-Hulud. Il récupère les clés SSH, les credentials cloud, les secrets CI/CD et les tokens Kubernetes, puis républie des packages empoisonnés pour se propager davantage. Cet article couvre la chaîne d’attaque complète, la nouvelle technique de contournement Phantom Gyp, et un guide pratique de durcissement.

32
Backdoored npm packages
Packages npm backdoorés
Source: Microsoft Security Blog, June 2026
90+
Trojanized versions published
Versions trojaniées publiées
Source: Microsoft Security Blog / Wiz Blog, June 2026
80K
Combined weekly downloads at risk
Téléchargements hebdo cumulés exposés
Source: Orca Security / Wiz Blog, June 2026
157B
Phantom Gyp binding.gyp size
Taille binding.gyp Phantom Gyp
Source: StepSecurity, June 2026
4.29MB
Obfuscated dropper payload size
Taille du dropper obfusqué
Source: Microsoft Security Blog, June 2026
236
Dead-drop repositories used
Dépôts dead-drop utilisés
Source: StepSecurity, June 2026

What Happened on June 1, 2026: The Miasma Attack Timeline

Ce qui s’est passé le 1er juin 2026 : La chronologie de l’attaque Miasma

The Miasma attack did not begin with a zero-day vulnerability. It began with a compromised human account. Evidence analysed by Microsoft Threat Intelligence indicates a Red Hat employee’s GitHub account was stolen — likely via stealer logs or phishing — giving the attacker write access to the RedHatInsights/javascript-clients monorepo and a second repository in the same organisation.

L’attaque Miasma n’a pas commencé par une vulnérabilité zero-day. Elle a commencé par un compte humain compromis. Les preuves analysées par Microsoft Threat Intelligence indiquent que le compte GitHub d’un employé Red Hat a été volé — probablement via des stealer logs ou du phishing — donnant à l’attaquant un accès en écriture au monorepo RedHatInsights/javascript-clients et à un second dépôt de la même organisation.

The attacker then pushed orphan commits directly into those repositories — commits that bypassed the normal pull request and code review workflow. The injected commits added a malicious GitHub Actions workflow that, when triggered, used the repository’s OIDC publishing token to call npm publish on 32 packages under the @redhat-cloud-services scope. Because the publish token was legitimately scoped to that namespace, npm accepted each upload and generated SLSA provenance attestations signed by the Sigstore certificate authority — the same attestations that tools like npm audit signatures use to verify package integrity. Every infected package appeared completely legitimate.

L’attaquant a ensuite pusé des commits orphelins directement dans ces dépôts — des commits qui ont court-circuité le processus normal de pull request et de revue de code. Les commits injectés ajoutaient un workflow GitHub Actions malveillant qui, une fois déclenché, utilisait le token OIDC de publication du dépôt pour appeler npm publish sur 32 packages du scope @redhat-cloud-services. Comme le token de publication était légitimement limité à ce namespace, npm acceptait chaque upload et générait des attestations de provenance SLSA signées par l’autorité de certification Sigstore — les mêmes attestations utilisées par des outils comme npm audit signatures pour vérifier l’intégrité des packages. Chaque package infecté semblait parfaitement légitime.

Phantom Gyp: How Miasma Bypasses npm Preinstall Security Checks

Phantom Gyp : Comment Miasma Contourne les Vérifications de Sécurité des Preinstall npm

Previous Shai-Hulud variants relied on preinstall lifecycle hooks to execute their payload. These hooks are increasingly flagged by security tooling, package auditors, and policies like --ignore-scripts. Miasma introduces a new technique that StepSecurity researchers named Phantom Gyp: a 157-byte binding.gyp file that abuses the native build pipeline to achieve code execution without a declared install script.

Les variantes précédentes de Shai-Hulud s’appuyaient sur des hooks de cycle de vie preinstall pour exécuter leur payload. Ces hooks sont de plus en plus signalés par les outils de sécurité, les auditeurs de packages et les politiques comme --ignore-scripts. Miasma introduit une nouvelle technique baptisée Phantom Gyp par les chercheurs de StepSecurity : un fichier binding.gyp de 157 octets qui exploite le pipeline de build natif pour obtenir l’exécution de code sans déclarer de script d’installation.

The mechanism works like this: when a package ships a binding.gyp file, npm automatically invokes node-gyp to compile native bindings — even when --ignore-scripts is set, because node-gyp is triggered by the presence of binding.gyp, not by the scripts field. The Miasma binding.gyp exploits the GYP_EVAL command-substitution feature of node-gyp to execute node index.js before any native compilation takes place:

Le mécanisme fonctionne ainsi : quand un package contient un fichier binding.gyp, npm invoque automatiquement node-gyp pour compiler les liaisons natives — même quand --ignore-scripts est activé, car node-gyp est déclenché par la présence de binding.gyp, non par le champ scripts. Le binding.gyp de Miasma exploite la fonctionnalité de substitution de commande GYP_EVAL de node-gyp pour exécuter node index.js avant toute compilation native :

{
  "targets": [{
    "target_name": "stub",
    "sources": ["<!(node index.js > /dev/null 2>&1 && echo stub.c)"]
  }]
}

The <!(...)> syntax is a GYP command-substitution expression evaluated at configuration time, before any build step. When node-gyp reads the file, it runs node index.js in the package directory. The malicious index.js is already present in the tarball — so the dropper executes immediately, silently, and without any declared lifecycle hook. The absence of a native module (stub.c) does not cause a build failure visible to the user; node-gyp emits a warning and exits quietly.

La syntaxe <!(...)> est une expression de substitution de commande GYP évaluée à l’étape de configuration, avant tout step de build. Quand node-gyp lit le fichier, il exécute node index.js dans le répertoire du package. L’index.js malveillant est déjà présent dans l’archive — le dropper s’exécute donc immédiatement, silencieusement, et sans aucun hook de cycle de vie déclaré. L’absence d’un module natif (stub.c) ne provoque pas d’erreur de build visible pour l’utilisateur ; node-gyp émet un avertissement et se termine silencieusement.

The Miasma Payload: Obfuscation, Bun Runtime & Multi-Cloud Credential Harvest

Le Payload Miasma : Obfuscation, Runtime Bun & Vol de Credentials Multi-Cloud

Once node index.js fires, the 4.29 MB dropper begins a multi-stage unpacking process. It uses several passes of ROT-based obfuscation (rotating character codes by varying offsets) followed by AES-128-GCM decryption to reconstitute the final payload in memory. The fully decoded stage then downloads the Bun JavaScript runtime from a legitimate CDN URL — using the system’s native curl or wget — and detonates the main stealer binary, which is a lightly reskinned descendant of the open-sourced Mini Shai-Hulud codebase, with several additions introduced specifically for this campaign.

Une fois node index.js déclenché, le dropper de 4,29 Mo démarre un processus de décompactage multi-étapes. Il utilise plusieurs passes d’obfuscation basée sur ROT (rotation des codes de caractères par des décalages variables) suivies d’un déchiffrement AES-128-GCM pour reconstituer le payload final en mémoire. L’étape entièrement décodée télécharge ensuite le runtime JavaScript Bun depuis une URL CDN légitime — en utilisant le curl ou wget natif du système — et détonne le binaire stealer principal, qui est un descendant légèrement modifié de la base de code Mini Shai-Hulud open-sourcée, avec plusieurs ajouts introduits spécifiquement pour cette campagne.

The credential harvest targets differ depending on the execution environment:

Les cibles de vol de credentials diffèrent selon l’environnement d’exécution :

On developer machines:

Sur les machines de développeurs :

Inside CI/CD runners (GitHub Actions, GitLab CI, Jenkins):

Dans les runners CI/CD (GitHub Actions, GitLab CI, Jenkins) :

Exfiltrated credentials are encrypted and committed as JSON files to a freshly created GitHub repository under the attacker-controlled account liuende501, which hosts 236 such dead-drop repositories. Each repository is named after the victim project and carries the description “Miasma: The Spreading Blight”. The public nature of these dead-drops allowed researchers to map the campaign’s breadth before takedown.

Les credentials exfiltrés sont chiffrés et committés sous forme de fichiers JSON dans un dépôt GitHub nouvellement créé sous le compte attaquant liuende501, qui héberge 236 de ces dépôts dead-drop. Chaque dépôt est nommé d’après le projet victime et porte la description “Miasma: The Spreading Blight”. La nature publique de ces dead-drops a permis aux chercheurs de cartographier l’étendue de la campagne avant la suppression.

Self-Propagation: How Miasma Spreads Through npm and Forges Provenance

Auto-Propagation : Comment Miasma Se Propage via npm et Forge la Provenance

The defining characteristic of the Shai-Hulud worm family is self-propagation. Once Miasma collects a victim’s npm publish token, it immediately attempts to republish every package that token has publish rights over. The republished versions are backdoored copies of the latest legitimate release, incremented by a patch version number and injected with the same Phantom Gyp payload. Crucially, if the stolen npm token is tied to a GitHub Actions OIDC workflow, the republished packages inherit the repository’s SLSA provenance workflow — generating cryptographically valid attestations for malicious packages.

La caractéristique définissante de la famille de vers Shai-Hulud est l’auto-propagation. Une fois que Miasma collecte le token de publication npm d’une victime, il tente immédiatement de républier chaque package sur lequel ce token a des droits de publication. Les versions républiées sont des copies backdoorées de la dernière version légitime, incrémentées d’un numéro de version patch et injectées avec le même payload Phantom Gyp. De façon cruciale, si le token npm volé est lié à un workflow OIDC GitHub Actions, les packages républiés héritent du workflow de provenance SLSA du dépôt — générant des attestations cryptographiquement valides pour des packages malveillants.

Miasma also includes a destructive failsafe: if the malware detects that a credential it harvested is a planted honeypot token (a technique used by some security teams), it executes rm -rf ~/ to wipe the victim’s home directory before exfiltrating and terminating. This anti-analysis measure underscores the operational sophistication of the campaign.

Miasma inclut également un mécanisme d’autodestruction : si le malware détecte qu’un credential récupéré est un token honeypot planté (une technique utilisée par certaines équipes de sécurité), il exécute rm -rf ~/ pour effacer le répertoire home de la victime avant d’exfiltrer et de se terminer. Cette mesure anti-analyse souligne la sophistication opérationnelle de la campagne.

The Shai-Hulud / Miasma Lineage: A Brief History of Self-Spreading npm Worms

La Lignée Shai-Hulud / Miasma : Bref Historique des Vers npm Auto-Propagants

Miasma is not an isolated campaign. It is the fourth documented wave of a worm family that has systematically escalated its techniques since late 2025:

Miasma n’est pas une campagne isolée. C’est la quatrième vague documentée d’une famille de vers qui a systématiquement éscaladé ses techniques depuis fin 2025 :

Detection: How to Know If You Installed a Miasma Package

Détection : Comment Savoir Si Vous Avez Installé un Package Miasma

The affected packages are all @redhat-cloud-services/*. Red Hat and npm removed the malicious versions on June 1 shortly after disclosure, but any system that ran npm install with a @redhat-cloud-services dependency between approximately 00:00 UTC and 14:00 UTC on June 1, 2026 should be treated as potentially compromised.

Les packages affectés sont tous des @redhat-cloud-services/*. Red Hat et npm ont retiré les versions malveillantes le 1er juin peu après la divulgation, mais tout système ayant exécuté npm install avec une dépendance @redhat-cloud-services entre environ 00h00 UTC et 14h00 UTC le 1er juin 2026 doit être considéré comme potentiellement compromis.

Check your lockfiles and build logs:

Vérifiez vos lockfiles et logs de build :

# Check package-lock.json
grep -r "@redhat-cloud-services" package-lock.json

# Check yarn.lock
grep "@redhat-cloud-services" yarn.lock

# Check pnpm-lock.yaml
grep "@redhat-cloud-services" pnpm-lock.yaml

# Check if Bun runtime was downloaded (indicator of compromise)
ls -la ~/.bun/bin/bun 2>/dev/null && echo "POTENTIAL IOC: Bun runtime found"

# Check for dead-drop repository creation in git config / SSH known hosts
grep "liuende501" ~/.ssh/known_hosts 2>/dev/null

If you run container images, scan them for the presence of @redhat-cloud-services packages built after June 1 using SBOM analysis. CVE OptiBot continuously monitors your lockfiles and alerts you when a new compromise is detected in your dependency tree — start free monitoring.

Si vous utilisez des images conteneurs, scannez-les pour détecter la présence de packages @redhat-cloud-services buildés après le 1er juin en utilisant l’analyse SBOM. CVE OptiBot surveille en permanence vos lockfiles et vous alerte quand un nouveau compromis est détecté dans votre arbre de dépendances — démarrez le monitoring gratuit.

Immediate Response & Remediation Checklist

Checklist de Réponse Immédiate & Remédiation

If you or your CI/CD pipeline installed any @redhat-cloud-services package between June 1 00:00 UTC and June 1 14:00 UTC, treat all secrets accessible from that environment as compromised and rotate immediately:

Si vous ou votre pipeline CI/CD avez installé un package @redhat-cloud-services entre le 1er juin 00h00 UTC et le 1er juin 14h00 UTC, traitez tous les secrets accessibles depuis cet environnement comme compromis et effectuez une rotation immédiate :

Hardening Guide: Preventing the Next Phantom Gyp Attack

Guide de Durcissement : Prévenir la Prochaine Attaque Phantom Gyp

Standard --ignore-scripts does not protect against Phantom Gyp, because the binding.gyp trigger happens in the node-gyp native build step, not in the scripts lifecycle. Effective protection requires multiple layers:

Le --ignore-scripts standard ne protège pas contre Phantom Gyp, car le déclencheur binding.gyp se produit dans l’étape de build natif node-gyp, pas dans le cycle de vie scripts. Une protection efficace nécessite plusieurs couches :

# 1. Block native builds entirely (if you don't need native modules)
npm config set ignore-scripts true          # blocks preinstall hooks
npm config set node-gyp /bin/false          # blocks binding.gyp execution

# 2. Use --foreground-scripts and audit output during install
npm install --foreground-scripts 2>&1 | tee install.log
grep -E "binding\.gyp|node-gyp|preinstall" install.log

# 3. In CI: run installs in a network-isolated sandbox
# Docker example: no outbound internet from npm install step
docker run --network none node:22-alpine npm ci

# 4. Pin dependencies to exact versions in lockfile
npm install --save-exact <package>
npm ci                                      # always use ci (not install) in pipelines

# 5. Audit SLSA provenance (does NOT detect Miasma, but useful for other attacks)
npm audit signatures

For CI/CD pipelines, the most effective single control is running npm ci inside a network-restricted container: if the dropper cannot reach the Bun CDN to download the runtime, it cannot detonate the final payload. This was identified as the most reliable mitigation by Orca Security and Microsoft Threat Intelligence.

Pour les pipelines CI/CD, le contrôle unique le plus efficace est d’exécuter npm ci dans un conteneur avec réseau restreint : si le dropper ne peut pas atteindre le CDN Bun pour télécharger le runtime, il ne peut pas détonner le payload final. Cela a été identifié comme la mesure d’atténuation la plus fiable par Orca Security et Microsoft Threat Intelligence.

For GitHub Actions specifically: limit the OIDC token permissions in your publish workflows to the exact scopes required, and enable environment protection rules that require a human reviewer to approve npm publish jobs. See our GitHub Actions OIDC Token Security guide for the full configuration.

Pour GitHub Actions spécifiquement : limitez les permissions du token OIDC dans vos workflows de publication aux scopes exactement nécessaires, et activez les règles de protection d’environnement qui nécessitent un relecteur humain pour approuver les jobs de publication npm. Consultez notre guide de sécurité des tokens OIDC GitHub Actions pour la configuration complète.

Frequently Asked Questions

Questions fréquentes

Does npm audit detect Miasma-infected packages?

npm audit détecte-t-il les packages infectés par Miasma ?

No. npm audit checks packages against the npm advisory database, which is populated reactively. The malicious @redhat-cloud-services versions were unpublished within hours of disclosure, so they no longer appear in audit results. However, if those versions are in your lockfile from a June 1 install, the installed code on disk is still compromised. Use SBOM scanning to detect historically compromised installs.

Non. npm audit vérifie les packages par rapport à la base de données d’advisories npm, qui est alimentée de manière réactive. Les versions malveillantes de @redhat-cloud-services ont été dépubliées dans les heures suivant la divulgation, donc elles n’apparaissent plus dans les résultats d’audit. Cependant, si ces versions figurent dans votre lockfile d’un install du 1er juin, le code installé sur disque est toujours compromis. Utilisez le scanning SBOM pour détecter les installations historiquement compromises.

Does --ignore-scripts protect against Phantom Gyp?

--ignore-scripts protège-t-il contre Phantom Gyp ?

No. --ignore-scripts suppresses preinstall, install, and postinstall lifecycle scripts defined in package.json. It does not suppress the node-gyp build step, which is triggered by the presence of binding.gyp regardless of the scripts field. To block Phantom Gyp, you must either set node-gyp to a no-op binary or run installs in a network-isolated environment where Bun cannot be downloaded.

Non. --ignore-scripts supprime les scripts de cycle de vie preinstall, install et postinstall définis dans package.json. Il ne supprime pas l’étape de build node-gyp, qui est déclenchée par la présence de binding.gyp indépendamment du champ scripts. Pour bloquer Phantom Gyp, vous devez soit définir node-gyp comme un binaire no-op, soit exécuter les installs dans un environnement isolé du réseau où Bun ne peut pas être téléchargé.

Are SLSA provenance attestations useless after Miasma?

Les attestations de provenance SLSA sont-elles inutiles après Miasma ?

SLSA provenance attestations are still valuable, but they prove where a package was built, not what the source code contained. Miasma shows that if an attacker controls the CI/CD pipeline (even temporarily via a compromised account), they can publish malicious code with valid provenance. The right interpretation of SLSA attestations is: “this package was built from this commit in this repository.” You must also verify that the commit was legitimate and the repository was not compromised.

Les attestations de provenance SLSA restent précieuses, mais elles prouvent un package a été construit, pas ce que le code source contenait. Miasma montre que si un attaquant contrôle le pipeline CI/CD (même temporairement via un compte compromis), il peut publier du code malveillant avec une provenance valide. L’interprétation correcte des attestations SLSA est : « ce package a été construit à partir de ce commit dans ce dépôt. » Vous devez également vérifier que le commit était légitime et que le dépôt n’a pas été compromis.

What is the relationship between Miasma and TrapDoor (May 2026)?

Quelle est la relation entre Miasma et TrapDoor (mai 2026) ?

TrapDoor (May 22, 2026) and Miasma (June 1, 2026) are distinct campaigns with different threat actors, targets, and TTPs. TrapDoor targeted crypto and DeFi developers across npm, PyPI, and Crates.io using typosquatting and AI assistant poisoning via .cursorrules and CLAUDE.md files. Miasma used account takeover of a verified corporate namespace with OIDC publishing access. Both demonstrate the escalating sophistication of npm supply chain attacks in mid-2026.

TrapDoor (22 mai 2026) et Miasma (1er juin 2026) sont des campagnes distinctes avec différents acteurs de menace, cibles et TTPs. TrapDoor ciblait les développeurs crypto et DeFi sur npm, PyPI et Crates.io via du typosquatting et l’empoisonnement d’assistants IA via les fichiers .cursorrules et CLAUDE.md. Miasma a utilisé la prise de contrôle d’un compte d’un namespace corporate vérifié avec accès de publication OIDC. Les deux démontrent la sophistication croissante des attaques de la chaîne d’approvisionnement npm à mi-2026.

Should I use npm ci or npm install in production?

Dois-je utiliser npm ci ou npm install en production ?

Always use npm ci in CI/CD pipelines. Unlike npm install, it installs exactly what is in your lockfile without updating it, fails if the lockfile is out of sync with package.json, and deletes node_modules before installing for a clean state. This prevents lockfile drift and reduces the window where a newly backdoored version could sneak in. See our npm package.json security best practices guide for the full lockfile integrity checklist.

Utilisez toujours npm ci dans les pipelines CI/CD. Contrairement à npm install, il installe exactement ce qui est dans votre lockfile sans le mettre à jour, échoue si le lockfile n’est pas synchronisé avec package.json, et supprime node_modules avant l’installation pour un état propre. Cela prévient la dérive du lockfile et réduit la fenêtre où une version nouvellement backdoorée pourrait s’introduire. Consultez notre guide des bonnes pratiques de sécurité npm package.json pour la checklist d’intégrité complète du lockfile.

How can I monitor my dependencies for future Miasma-style attacks?

Comment surveiller mes dépendances contre les futures attaques de type Miasma ?

CVE OptiBot scans your package-lock.json, yarn.lock, and pnpm-lock.yaml daily against the OSV.dev and GitHub Advisory databases and alerts you instantly when a package in your dependency tree is flagged — including supply chain compromises, not just traditional CVEs. You can also set up lockfile monitoring for your entire project portfolio from a single dashboard.

CVE OptiBot scanne votre package-lock.json, yarn.lock et pnpm-lock.yaml quotidiennement par rapport aux bases de données OSV.dev et GitHub Advisory, et vous alerte instantanément quand un package de votre arbre de dépendances est signalé — y compris les compromissions de chaîne d’approvisionnement, pas seulement les CVE traditionnelles. Vous pouvez également configurer le monitoring de lockfile pour l’ensemble de votre portfolio de projets depuis un seul tableau de bord.

Don’t Wait for the Next Worm to Hit Your Supply Chain

N’attendez Pas que le Prochain Ver Frappe Votre Chaîne d’Approvisionnement

Miasma, TanStack, CanisterWorm — supply chain worms that forge valid SLSA provenance are the new normal. CVE OptiBot scans your lockfiles daily and alerts you the moment a dependency in your project is flagged for compromise, backdoor, or malicious behaviour — before your CI/CD pipeline runs it.

Miasma, TanStack, CanisterWorm — les vers de chaîne d’approvisionnement qui forgent une provenance SLSA valide sont la nouvelle normalité. CVE OptiBot scanne vos lockfiles quotidiennement et vous alerte dès qu’une dépendance de votre projet est signalée pour compromission, backdoor ou comportement malveillant — avant que votre pipeline CI/CD ne l’exécute.

Start free dependency monitoring Démarrer le monitoring de dépendances gratuit