
Your CI pipeline ran npm install this morning. Somewhere in your dependency tree, a patch version bumped overnight with no changelog and no PR, and a credential-harvesting payload pulled secrets from process.env and used a stolen npm token to infect the next wave of packages downstream.
That's the Shai-Hulud attack chain. It's a self-propagating npm worm that compromised hundreds of packages, exfiltrated credentials from build environments, and used those credentials to keep spreading — without any human operator in the loop. Removing the compromised package doesn't end the compromise. The stolen tokens, the rogue GitHub Actions runners, and the exfiltrated cloud credentials all survive cleanup unless you know where to look.
This article walks through the full attack chain, breaks down what changed in V2, and covers the detection rules and remediation steps your team needs to contain this class of supply chain compromise.
Key Takeaways:
Shai-Hulud is a self-propagating npm worm formally documented by CERT/CC advisory and described by CISA alert.
V2 introduced significant evasion and persistence changes, including
preinstallexecution before installation completes, runner persistence, and destructive behavior if credential theft failed.Removing the compromised package does not end the compromise. Full credential rotation and runner persistence auditing are required.
Behavioral detection is essential because the payload can change form while preserving the same operational steps.
What Is the Shai-Hulud npm Supply Chain Attack
Shai-Hulud is a self-replicating worm targeting the npm ecosystem at scale. Named after the workflow file shai-hulud-workflow.yml dropped by the malware, a reference to the sandworms in Dune, it was formally documented by CERT/CC advisory as a self-propagating malware variant.
Timeline: From V1 to "The Second Coming"
The campaign emerged in September 2025 amid maintainer phishing compromises that affected widely used npm packages. Within days, the number of impacted packages had grown rapidly.
A more advanced second wave followed. On November 24, 2025, public disclosures described a significantly evolved variant. V2 was later reported as contained in early December 2025, and later variants continued into 2026.
Scale of the Compromise
The second wave impacted hundreds of npm packages in the npm registry, with substantial credential exposure across large numbers of auto-generated GitHub repositories. Critically, stolen credentials could remain usable after the initial spread slowed, meaning future attacks could continue even after containment of the active worm.
How the Attack Works
Shai-Hulud operates as a five-phase attack chain: phish a maintainer, harvest credentials from the build environment, exfiltrate them, then use the stolen npm token to infect the next wave of packages. Each phase crosses team boundaries, starting in npm, moving to GitHub, then landing in cloud infrastructure.
That cross-domain sprawl is why these incidents are hard to contain. As Matthew Martin, Founder of Two Candlesticks, said, "I think historically we haven't done a good job of understanding the sort of the holistic flow of our data and where it goes throughout our vendor ecosystem."
1. Initial Access: Phishing npm Maintainers
The precursor compromise of maintainer Josh Junon used support [at] npmjs [dot] help, a lookalike site that prompted the maintainer to "update" their 2FA credentials. The fake login page captured username, password, and a live TOTP code in real time, defeating standard authenticator-app MFA. The phishing campaign targeting npm publishing tokens used a npnjs.com typosquatted domain, while ClickFix lures during fake video calls have been observed in separate campaigns distributing infostealers, not stealing npm publishing tokens.
2. Credential Harvesting and Exfiltration
Once a trojanized package executes, it collects secrets from the runtime environment, including environment variables and credentials available to the build or developer system. Technical analysis of the incident focused on compromise of GitHub Actions and exfiltration of GitHub-related tokens and repository configuration.
Exfiltration used multiple channels during the campaign, including GitHub-hosted infrastructure and malicious workflow files under .github/workflows/.
3. Self-Propagation Through npm Lifecycle Scripts
After harvesting credentials, the payload enabled follow-on malicious package publication. The attack inserted a malicious lifecycle hook and published compromised package versions. The malicious code preserved normal package behavior while continuing to spread — downstream consumers saw no functional difference.
What Changed in Shai-Hulud 2.0
V2 introduced substantial upgrades across execution, persistence, and failsafe capabilities. Each change affects both prevention and detection, so the subsections below map V2's evolution to concrete response steps.
1. Preinstall Execution and Bun-Based Payloads
V2 changed when and how the payload runs. V1 used postinstall hooks running on Node.js. V2 switched to preinstall hooks and a Bun-based runtime. As Check Point Research stated: "Unlike traditional malware that activates after installation, this campaign abuses the npm preinstall lifecycle script, allowing the malicious payload to run before installation completes and even when installation fails."
The Bun runtime switch was intentionally chosen: "Most security tools and sandboxes are optimized to track Node.js behavior, which makes Bun an attractive way to operate outside common detection paths." AI-based classification tools also failed on some V2 payloads — a direct consequence of the runtime switch.
2. Persistent Backdoors via GitHub Actions Runners
V2 used GitHub Actions self-hosted runner registration to maintain access and enable arbitrary command execution through GitHub's own infrastructure. Rogue workflow files and runner registration served as persistence mechanisms that maintained access beyond the initial package installation.
Commands arriving via GitHub's legitimate Actions infrastructure make this persistence especially difficult to detect. Network detections looking for known malicious IPs will not flag connections to GitHub's API endpoints.
3. The Dead Man's Switch
V2 introduced a destructive failsafe. If the worm couldn't steal your credentials, it could still compromise the system.
Immediate Remediation Steps
Removing the package alone does not resolve the compromise. The attack begins in npm and can end as a backdoor in cloud infrastructure. The JavaScript team won't detect it because the compromise immediately leaves their domain. The cloud team will miss it because it arrived from a trusted CI pipeline. Cross-team execution is mandatory.
The remediation work falls into three tracks: identify affected packages and artifacts, rotate exposed credentials, and review GitHub for persistence. The subsections below follow that order so you can handle immediate containment before longer follow-up work.
1. Audit Dependencies and Pin Safe Versions
Start by identifying whether any compromised packages or artifacts are present in your environment. Cross-reference installed packages against known compromised-package reporting and search your filesystem for malware artifacts:
Pin all dependencies to exact versions and use npm ci in CI pipelines. Run npm audit signatures to verify ECDSA registry signatures.
2. Rotate All Exposed Credentials
Treat any environment where a compromised package ran as fully exposed. The malware captures the runtime environment, which can include npm tokens, GitHub PATs, cloud access keys, and other injected secrets. Revoke all classic npm tokens and replace them with granular tokens.
Rotate GitHub tokens and AWS or other cloud access credentials. Because the malware also searched for additional secrets, review and rotate other credentials exposed to affected CI or developer environments as needed.
3. Review GitHub for Indicators of Compromise
Review GitHub for persistence and unauthorized changes. Search your GitHub organization for suspicious repositories created during the incident, unexpected workflow files, and self-hosted runners that should not exist. Audit workflow files for unauthorized additions, particularly any committed via direct push without a pull request.
Detecting Supply Chain Compromise in Your Security Data
Behavioral detection provides the most durable control here. Remediation addresses the immediate threat, but long-term coverage depends on ingesting the right log sources, writing behavioral detection rules, and understanding why signatures alone will not work.
This section breaks detection into pipeline behavior, cloud credential abuse, and behavior-first rule design. Together, those areas show how to connect package execution, GitHub activity, and downstream cloud misuse in one investigation path.
Monitoring CI/CD Pipelines for Anomalous Behavior
Start with the behaviors the attack must perform. Focus detection rules on behaviors the attack must perform, regardless of payload obfuscation:
Unexpected network connections: Any outbound connection from a CI runner during
npm installto a domain outside your approved registry allowlistShell process spawning:
bash,sh,curl, orwgetspawned as children ofnodeornpmduring lifecycle hook executionWorkflow injection: New
.github/workflows/*.ymlfiles committed without a corresponding pull request
Critical log sources include GitHub logs, CI runner process execution logs, DNS queries from build runners, AWS CloudTrail, and GitHub audit logs. For teams running Panther, these map to its native integrations and security data lake for cloud and SaaS sources.
Tracking Cloud Credential Abuse After Exfiltration
Credential theft usually shifts the attack into cloud infrastructure. Monitor AWS CloudTrail for CreateAccessKey, CreateUser, and AttachUserPolicy events. Watch for GetCallerIdentity calls, often an early API call in credential-abuse activity, from unexpected source IPs.
Correlate CI runner IP ranges with API call timestamps: CloudTrail events from runner IPs outside scheduled build windows strongly indicate stolen credential reuse. Docker case study faced similar cross-cloud visibility challenges and achieved 85% false positive reduction after centralizing detection through correlation rules.
Why Behavioral Detection Matters When Malware Is AI-Generated
Behavior survives even when payloads change form. Signature-based detection is structurally insufficient here. AI-generated polymorphism can produce behaviorally similar malware in different code forms, weakening signature matching. Behavior-based detection targets attacker intent directly — what the payload does, not what it looks like.
Target the invariant behavioral properties that survive syntactic mutation: credential file access followed by outbound network connections, process lineage chains, and API call sequences. A detection rule that correlates node reading ~/.npmrc or ~/.aws/credentials with a near-term outbound HTTPS connection may help identify this type of attack.
Write these rules in Python, SQL, or YAML. In Panther docs, they can be version-controlled, unit-tested, and deployed through CI/CD pipelines, so you iterate on supply chain detection rules the same way you ship application code.
Building Long-Term Supply Chain Resilience
Long-term resilience depends on reducing token exposure and integrating supply chain signals into your detection workflow. The controls below focus on the two main lessons from the campaign: reduce exposure for non-human identities, and pull npm, GitHub, CI/CD, and cloud signals into the same operational workflow.
Treating Non-Human Identities as a First-Class Attack Surface
npm tokens, GitHub PATs, and CI/CD service accounts are the common thread across major npm compromises. The practical path forward:
Migrate to npm Trusted Publishing to eliminate npm tokens entirely for CI publishing
Replace stored cloud keys with OIDC federation (GitHub Actions → AWS/GCP/Azure)
Pin GitHub Actions to commit SHAs, not tags. Tags are mutable and can be redirected
Enforce phishing-resistant MFA (FIDO2/passkeys) on all npm and GitHub accounts. Standard TOTP was bypassed in real time during maintainer phishing compromises
Establish an NHI lifecycle discipline: inventory → ownership → certification → rotation → monitoring → decommissioning. Unowned NHIs with active credentials are your highest-priority triage category
Integrating Supply Chain Signals Into Your Security Operations
Supply chain attacks show up across npm, GitHub, CI/CD pipelines, and cloud IAM, so your security operations need those signals in one place. Gaps in telemetry from sources like npm, GitHub, CI/CD, and cloud IAM can make these attacks harder to detect.
As Jason Craig of Remitly says, "Once you have observable data and an understanding of your environment, you can more easily build your detection and response strategies."
Integrate these signals into tiered alerting:
Tier 1 (immediate response): Outbound connections from CI runners to
webhook.site, npm tokens in public repositories, or post-install scripts executing outbound network callsTier 2 (investigation required): New package versions published with no corresponding source code change, or workflows modified to access new secrets
Tier 3 (threat hunting): Dependency version drift from pinned lockfile versions, new maintainers on critical upstream packages, or OpenSSF Scorecard score degradation
Intercom built this kind of cross-source investigation capability, tackling threats 2X faster after consolidating detection workflows. For lean security teams, the difference between a contained incident and a full compromise often comes down to how fast you can correlate across these domains.
Shai-Hulud showed that supply chain attacks can be automated, self-propagating, and designed to cross team boundaries in your organization. Your detection and alerting capability needs to cover that scope.
Share:
RESOURCES






