Preinstall to persistence: Inside the Red Hat npm Miasma credential-stealing campaign
Microsoft Threat Intelligence has uncovered a large-scale supply chain attack targeting the @redhat-cloud-services npm scope, with 32 packages compromised across more than 90 versions. The attack originated from a hijacked CI/CD pipeline belonging to the RedHatInsights/javascript-clients repository, allowing attackers to publish malicious packages through a legitimate GitHub Actions OIDC publishing workflow. The trojanized packages carried valid provenance signatures while embedding the campaign marker "Miasma: The Spreading Blight."
How the Attack Worked
Once a compromised package was installed, a preinstall hook automatically executed a heavily obfuscated 4.29 MB dropper script — no user interaction required. The dropper worked through multiple layers of obfuscation and encryption before downloading the Bun JavaScript runtime and launching a secondary payload designed to steal credentials from GitHub, npm, AWS, Azure, Google Cloud Platform, HashiCorp Vault, Kubernetes, and developer workstations. The malware could also spread by compromising additional packages owned by affected maintainers, and in some cases wiped the victim's home directory entirely.
The payload ran on Linux, macOS, and Windows by dynamically fetching the appropriate Bun runtime per platform, though Linux CI/CD runners appeared to be the primary target.
Ten-Phase Attack Chain
The malware progressed through a structured sequence of operations:
Delivery — Infection triggered automatically via the npm preinstall hook during package installation
Unpacking — Multiple decoding layers including ROT-based obfuscation and AES-128-GCM decryption
Environment checks — Validates execution environment; terminates on systems with limited locale settings
Defense evasion — Attempts to neutralize active security controls
Credential theft — Harvests tokens and secrets from GitHub, npm, major cloud providers, Vault, and Kubernetes, including direct scraping of CI runner process memory
Privilege escalation — Installs a passwordless sudo rule for elevated system access
Persistence — Monitors stolen tokens and stages secondary payload deployment
Exfiltration — Transmits stolen data via three separate command-and-control channels, including abuse of GitHub infrastructure
Self-propagation — Republishes packages with forged provenance metadata, spreading like a worm across trusted package ecosystems
Destructive tripwire — If a planted decoy token is triggered, executes a wipe command (rm -rf ~/) destroying the victim's home directory
Obfuscation in Depth
The dropper employed four distinct obfuscation stages to resist analysis. The outer layer used a large character-code array decoded via a ROT Caesar cipher transformation and executed dynamically. The next layer decrypted two AES-128-GCM encrypted blobs — one to download the Bun runtime, the other containing the core payload. That payload was further protected using Obfuscator.io techniques including rotated string arrays and hundreds of alias wrappers. Finally, sensitive strings were encrypted using a custom routine based on PBKDF2-HMAC-SHA-256 with 200,000 iterations, followed by multiple permutation and XOR stages to complicate reverse engineering.
What Was Stolen
The credential harvester targeted a broad range of platforms. From GitHub it validated token scopes, enumerated repositories, read Actions and organization secrets, and stole runtime tokens. From npm it exchanged OIDC tokens for publishing rights and identified maintainer-owned packages for poisoning. Cloud credential theft covered AWS IAM via IMDS and ECS metadata, Azure OAuth2 tokens for management and Key Vault endpoints, and GCP service account tokens and Secret Manager access. On developer systems it exfiltrated SSH keys, CLI credentials, browser data, and cryptocurrency wallet files. In CI/CD environments it scraped GitHub Actions runner process memory directly to bypass secret masking.
Exfiltration Channels
Rather than relying on a single command-and-control endpoint, the malware used three channels. First, it created a public GitHub repository under the victim's account and committed stolen credential data as JSON files. Second, it injected its own source code into non-protected branches across victim-owned repositories via the Git Data API, using spoofed commit metadata to blend in. Third, it included a dormant HTTPS exfiltration path targeting api.anthropic.com — the same domain used to validate stolen Anthropic API keys — indicating a swappable live exfiltration path that was not yet activated in this sample. C2 traffic rotated across 16 attacker-controlled GitHub accounts per session, with stolen tokens double-Base64 encoded in transit.
Scope and Impact
Thirty-two packages under the @redhat-cloud-services scope were affected across more than 90 malicious versions. The blast radius extended far beyond direct installations — stolen npm tokens enabled further package poisoning, stolen GitHub tokens enabled repository manipulation, and stolen cloud credentials enabled broader infrastructure access. Forged SLSA provenance attestations via Sigstore undermined trust in supply chain verification frameworks more broadly.
Microsoft shared its findings with the npm security team, which removed the affected packages and implemented additional protections on the @redhat-cloud-services namespace.
Recommended Actions
Organizations should audit their dependency trees for direct or transitive use of affected packages, identify any systems that installed compromised versions during the exposure window, and pin known-good versions where possible. Running npm install --ignore-scripts disables pre- and post-install hooks and prevents this class of attack. All credentials, tokens, CI/CD secrets, and cloud credentials that may have been exposed should be rotated immediately. GitHub accounts should be audited for unexpected public repositories bearing the description "Miasma: The Spreading Blight." CI/CD logs should be reviewed for unexpected outbound connections, and npm lockfiles and build artifact provenance should be inspected for evidence of compromise.