[email protected] Supply Chain Attack Enables Credential Theft: Shai-Hulud Strikes Again
Executive Summary
[email protected] is a compromised npm package used in a supply chain attack to steal GitHub, npm, and multi-cloud credentials. The malicious version introduces a preinstall hook that executes an obfuscated payload, harvesting secrets and exfiltrating them via GitHub APIs. This activity is part of the Shai-Hulud worm campaign targeting CI/CD pipelines.
Detection Summary
Earlier today, our security team detected a compromise in intercom-client – the official Node.js SDK for Intercom’s customer messaging platform, with over 361,000 weekly downloads. Version 7.0.4, published this morning, had been tampered with and turned into a multi-cloud credential stealer. Despite the package’s massive reach, none of Upwind’s customers downloaded the malicious version.
Upwind detected the threat approximately ~20 minutes after it was published – before it could reach any customer environment. That speed wasn’t luck. Upwind’s detection was powered by an internal scanning engine developed in-house – a purpose-built system that continuously monitors newly published npm package versions for supply chain tampering and malicious code, allowing us to identify the threat independently and ahead of the broader community.
This post is our account of what we found, why it matters beyond this single package, and what teams should do about it.

Background: A Worm, Not an Accident
This compromise did not happen in isolation. It is the third known victim of a coordinated supply chain worm campaign, tracked internally by the security community as Shai-Hulud, that has been propagating through CI/CD infrastructure since at least late 2025.
The mechanics are straightforward and brutal: the worm steals npm publish tokens and GitHub OIDC credentials from infected CI/CD pipelines, then uses them to publish poisoned versions of other packages that those pipelines have publish rights to. Each new victim becomes a propagation vector.
[email protected] was published on April 30, 2026, at 14:41 UTC. The publisher identity in the npm registry shows [email protected] – a GitHub Actions OIDC token. The Intercom engineering team did not publish this version. Their CI/CD pipeline was used against them.
What’s Inside 7.0.4
The malicious version is almost indistinguishable from 7.0.3 at the surface. The legitimate SDK code is intact. The package works exactly as expected. That’s by design.
What changed:
package.json gained a single new line:
"preinstall": "node setup.mjs"Copied
Two new files appeared that have no history in the package’s GitHub repository:
setup.mjs– 6,780 bytes, 222 linesrouter_runtime.js– 11,731,860 bytes, a single obfuscated line
The unpacked size jumped from 6 MB to 17.8 MB. SLSA provenance attestations, present in 7.0.3, are absent entirely.
The Loader – setup.mjs
The preinstall hook executes setup.mjs, which only acquires the Bun JavaScript runtime and uses it to run router_runtime.js. Bun is downloaded directly from GitHub releases, a trusted domain. If Bun is already installed on the system, it reuses the existing installation.
The choice of Bun over Node.js is deliberate: most EDR and SIEM detection rules that flag suspicious subprocess activity during npm install are tuned for node child processes. A bun process flies entirely under that radar.
The loader correctly handles Alpine/musl environments, includes a pure-Node ZIP parser fallback for minimal container images, and cleans up after itself – deleting the downloaded zip and Bun binary on exit to reduce forensic footprint.
The Payload – router_runtime.js
This is the credential harvester. At 11.7 MB with zero newlines, it is a single obfuscated line encoding a full multi-cloud credential sweep:
- GitHub tokens – Personal access tokens (
ghp_*), OAuth tokens (gho_*), and Actions/OIDC tokens (ghs_*) - npm tokens – Publish access tokens matching
npm_[A-Za-z0-9]{36,}. Stolen tokens are what enable worm propagation. - AWS credentials – Queries the Instance Metadata Service at
http://169.254.169.254for role credentials. Also scans environment variables and config files foraws_secret_access_key,aws_session_token, and access key ID patterns (AKIA[A-Z0-9]{16}). - GCP credentials – Queries
http://metadata.google.internalfor service account tokens. Scans for Application Default Credentials JSON files. - Azure credentials – Scans for storage connection strings, client secrets, and access keys matching patterns like
AccountKey,accessKey, andclient_secret. - Private keys and generic secrets – PEM-encoded RSA and ECDSA keys, and broad pattern matching on variables named
password,secret,token,api_key, and similar.
The payload also detects CI/CD environments specifically and activates targeted collection behavior, including GitHub Actions, Vercel, and generic CI environments.
Exfiltration
Nothing goes to an unknown command-and-control domain. Everything goes to api.github.com.
Using the stolen GitHub token, the payload authenticates, creates a private repository under the victim’s account, and commits the harvested credentials there. From a network monitoring perspective, this is indistinguishable from a developer pushing code. The domain is trusted. The traffic is HTTPS. Standard egress controls, domain blocklists, and IP-based detection are useless here.
What We Observed at Upwind
Upwind flagged [email protected] as malicious roughly 20 minutes after it was published – well before it could propagate through customer pipelines. Around 15% of our customers have an intercom-client in their dependency tree. None of them installed the malicious version.
What surfaced wasn’t a CVE match or a known-bad hash. It was behavioral. Three risk patterns fired simultaneously:
- A preinstall hook appeared for the first time in a package that had never used one across its entire version history. an immediate anomaly signal.
- Two undocumented files were injected (
setup.mjsandrouter_runtime.js) with no corresponding commits in the upstream GitHub repository. The package size tripled in a single patch bump. - SLSA provenance attestations were absent. Version
7.0.3carried them.7.0.4did not. means this publish did not come from the legitimate Intercom CI workflow that generates them.
None of these signals would have surfaced through traditional vulnerability scanning. This is exactly the kind of attack that slips through when detection relies on known signatures rather than behavioral baselines.
What To Do Now
- Check if you’re affected: Search your dependency tree and lockfiles for
[email protected]. Also look for the two malicious files –setup.mjsandrouter_runtime.js– inside the package’snode_modulesdirectory. Either finding confirms a compromised install. - Downgrade and reinstall cleanly: Remove
7.0.4and explicitly pin to7.0.3. When reinstalling, use the--ignore-scriptsflag to prevent any lifecycle hooks from executing. - Rotate all credentials that were in scope: Any GitHub tokens, npm publish tokens, or cloud credentials (AWS, GCP, Azure) accessible to a pipeline that ran this install should be treated as compromised and rotated immediately – don’t wait to confirm exfiltration.
Attacks Aren’t Slowing Down
This isn’t a one-off incident. Over the past 12 months, we’ve seen a steady and accelerating rise in supply chain attacks targeting npm, PyPI, and other package ecosystems. What’s changed isn’t just the frequency – it’s the sophistication. Attackers are no longer uploading obvious typosquats. They’re compromising legitimate maintainer accounts, hijacking CI/CD pipelines, and publishing malicious versions under trusted identities. The package looks right. The publisher looks right. The version bump looks routine.
Shai-Hulud is a particularly sharp example of where this threat is headed: a self-replicating worm that uses each victim’s infrastructure to find and infect the next target, expanding its credential harvest with each generation. Today, it’s AWS, GCP, and Azure tokens. Tomorrow, it’s whatever sits in your pipeline environment.
At Upwind, supply chain threat detection is built into our monitoring of cloud-native environments. We watch for anomalous package behavior at install time, correlate it against runtime activity across CI/CD pipelines and cloud workloads, and surface signals early. As today’s 20-minute detection demonstrates. If you’re running Node.js services in AWS, GCP, or Azure and want to understand your exposure to this class of attack, we’d like to talk.


