Shai-Hulud Campaign: Why This Attack Is Different
The Shai-Hulud campaign marks a turning point in how supply chain attacks are executed in the npm ecosystem. This is not simply about poisoning a popular package and waiting for downloads. What makes Shai-Hulud genuinely dangerous is that it turns compromised developers into infrastructure, allowing the malware to spread autonomously using legitimate credentials, trusted workflows, and normal developer behavior.
Instead of breaking into systems, the attackers let developers unknowingly open the doors themselves.
Scale and Real-World Impact
Telemetry and investigation conducted by Expel shows the campaign has achieved a level of scale rarely seen in open-source supply chain attacks.
Key impact metrics observed so far:
- Over 25,000 GitHub repositories touched or exposed
- Hundreds of npm packages directly compromised
- More than 795 confirmed infected packages identified across multiple waves
- Combined downstream exposure exceeding 100 million monthly downloads
High-visibility projects linked to affected packages include:
- Zapier
- ENS Domains
- AsyncAPI
- PostHog
- Browserbase
- Postman
Because these tools are deeply embedded in enterprise CI/CD pipelines, the blast radius extends far beyond individual developers into production build systems and cloud environments.
Timeline: From Initial Breach to Worm-Scale Propagation
The campaign first appeared in September 2024, beginning with the compromise of the widely used @ctrl/tinycolor library. At that stage, activity resembled a traditional credential-driven package compromise.
The situation escalated dramatically in November 2025, when defenders began observing what researchers now refer to as:
- “Shai-Hulud 2.0”, or
- “Sha1-Hulud: The Second Coming”
This second wave introduced:
- Faster propagation logic
- Abuse of
preinstalllifecycle hooks - Autonomous package publishing
- Destructive fallback mechanisms
Within 72 hours, more than 25,000 GitHub repositories were compromised or leveraged, confirming the malware was no longer manually operated at each step.
Technical Attack Methodology
Initial Access: Credential Harvesting at Scale
The campaign commonly begins with phishing emails spoofing npm security alerts, prompting developers to “verify” their accounts. These messages are convincing enough to harvest:
- npm authentication credentials
- GitHub personal access tokens
- OAuth tokens tied to CI systems
In parallel, attackers leverage previously leaked or reused tokens obtained from unrelated breaches, allowing silent access without triggering user interaction.
Once inside a single developer environment, the malware immediately pivots to collect additional secrets, including:
- npm publish tokens
- GitHub Actions secrets
- CI/CD credentials
- Cloud credentials across AWS, Azure, and GCP
At this point, the attacker no longer needs to maintain persistence—the credentials are the persistence mechanism.
Lifecycle Script Exploitation: Preinstall as a Weapon
Shai-Hulud 2.0 introduced a critical tactical shift: preinstall hooks.
Instead of relying on postinstall scripts, the malware embeds itself in the preinstall lifecycle phase inside package.json. This ensures:
- Code executes before files are fully written to disk
- Security scanners never see the payload at rest
- Execution happens automatically during
npm install - No user interaction is required
The script executes with the exact privileges of the user or CI runner, granting immediate access to environment variables, token stores, SSH keys, and cloud metadata endpoints.
This is one of the most effective execution primitives currently available in the npm ecosystem.
Credential Harvesting and Exfiltration
Once running, the malware performs aggressive reconnaissance. It enumerates:
- Environment variables
~/.npmrc~/.gitconfig~/.ssh/~/.aws/credentials- GCP application default credentials
- Azure profiles
For cloud environments, the malware directly interacts with native APIs:
- AWS Secrets Manager (using SDK pagination)
- Google Secret Manager via
@google-cloud/secret-manager
GitHub-Based Exfiltration
One of the more novel aspects of Shai-Hulud is how it exfiltrates data.
Instead of sending secrets to external servers, the malware:
- Uses stolen GitHub tokens
- Creates new public repositories under the victim’s account
- Commits stolen credentials directly into those repositories
- Leaves them publicly accessible
Repository names are often random 18-character strings, with descriptions referencing phrases such as:
- “Sha1-Hulud: The Second Coming”
- “Sha1-Hulud: The Continued Coming”
This technique blends seamlessly into normal GitHub activity and bypasses many traditional data loss prevention controls.
Worm-Like Self Propagation
What truly separates Shai-Hulud from prior supply chain campaigns is its self-replicating behavior.
After harvesting credentials, the malware:
- Authenticates to npm using the victim’s token
- Enumerates other packages maintained by that developer
- Injects malicious lifecycle scripts into those packages
- Publishes new compromised versions automatically
No additional attacker input is required. Each compromised developer becomes a new propagation node.
Destructive Fallback Behavior
If the malware fails to exfiltrate credentials or authenticate successfully, it does not simply exit.
In these cases, Shai-Hulud 2.0 activates wiper-style logic, attempting to destroy the victim’s home directory. This marks a shift from pure credential theft into punitive sabotage, increasing both operational risk and psychological impact.
Indicators of Compromise (IOCs)
File-Based Indicators
Common malicious artifacts observed include:
setup_bun.jsbun_environment.js
(approximately 480,000 lines of heavily obfuscated JavaScript)
Workflow Artifacts
.github/workflows/shai-hulud-workflow.yml.github/workflows/discussion.yaml
Data Staging Files
cloud.jsoncontents.jsonenvironment.jsontruffleSecrets.jsonactionsSecrets.json
Additional Indicators
~/.truffler-cache/~/.dev-env/(GitHub runner artifacts)
Runtime, Network, and API Indicators
Runtime & Process Indicators
Watch for:
- Node.js executing
setup_bun.jsorbun_environment.js - Bun runtime spawning child processes that access credential files
- TruffleHog running unexpectedly on developer machines
- GitHub Actions runners registering with the name SHA1HULUD
Network & API Indicators
Suspicious activity includes:
- GitHub API calls creating repositories without user interaction
- Unauthorized workflow file creation or modification
- npm publish operations outside normal release cycles
- Cloud API calls to:
secretsmanager.*.amazonaws.comsecretmanager.googleapis.comregistry.npmjs.org
Why This Campaign Matters Long-Term
Shai-Hulud is not limited to npm. The underlying technique—credential-driven trust abuse—applies equally well to:
- PyPI (Python)
- RubyGems (Ruby)
- Composer (PHP)
Any ecosystem that relies on implicit trust between maintainers, registries, and CI pipelines is vulnerable.
Once cloud credentials are stolen, the blast radius expands beyond software supply chains into:
- Cloud storage theft
- Ransomware deployment
- Cryptomining
- Production environment deletion
CI-Focused Detection and Hunting
Because Shai-Hulud is designed to execute automatically during dependency installation, CI/CD environments provide the cleanest and highest-confidence detection surface. CI runners execute code without user interaction, hold powerful credentials, and are often implicitly trusted.
The detection logic below focuses specifically on CI environments, where signal-to-noise ratios are significantly better than on developer endpoints.
Note: Field names and log sources may vary depending on CI platform and telemetry tooling. These rules are intended as detection logic, not drop-in signatures.
Detection 1: npm Lifecycle Script Execution in CI
title: CI npm Lifecycle Script Execution
logsource:
category: process_creation
product: linux
detection:
selection:
Image|endswith: [npm, node]
CommandLine|contains: [preinstall, postinstall, install]
ci_env:
Environment|contains: [CI=true, GITHUB_ACTIONS=true, GITLAB_CI=true]
condition: selection and ci_env
level: high
Detection 2: Credential Access During Dependency Installation
title: CI Credential Harvest During npm Install
logsource:
category: file_access
product: linux
detection:
selection:
ProcessImage|endswith: [npm, node]
TargetFilename|contains:
- .npmrc
- .aws/credentials
- application_default_credentials.json
- .ssh/
ci_env:
Environment|contains: [CI=true]
condition: selection and ci_env
level: critical
Detection 3: GitHub Repository Creation from CI
title: CI GitHub Repository Creation
logsource:
product: github
service: audit
detection:
selection:
action: repo.create
actor_location: [github_actions, gitlab_ci]
condition: selection
level: high
Detection 4: Unauthorized npm Publish in CI
title: CI npm Publish Outside Approved Workflow
logsource:
category: process_creation
product: linux
detection:
selection:
Image|endswith: npm
CommandLine|contains: publish
ci_env:
Environment|contains: [CI=true]
condition: selection and ci_env
level: critical
Detection 5: Cloud Secret Manager Access During Install
title: CI Cloud Secret Enumeration
logsource:
category: network_connection
product: linux
detection:
selection:
DestinationHostname|contains:
- secretsmanager.amazonaws.com
- secretmanager.googleapis.com
parent_process:
ProcessParent|endswith: [npm, node]
ci_env:
Environment|contains: [CI=true]
condition: selection and parent_process and ci_env
level: critical
Detection 6: Known Shai-Hulud Artifacts in CI
title: Shai-Hulud Artifact Detection
logsource:
category: file_creation
product: linux
detection:
selection:
TargetFilename|endswith:
- setup_bun.js
- bun_environment.js
- shai-hulud-workflow.yml
- discussion.yaml
ci_env:
Environment|contains: [CI=true]
condition: selection and ci_env
level: critical
Detection 7: Malicious GitHub Runner Registration
title: Suspicious GitHub Runner Registration
logsource:
product: github
service: audit
detection:
selection:
action: org.self_hosted_runner.registered
runner_name|contains: SHA1HULUD
condition: selection
level: critical
Correlation Guidance
Treat this as an active Shai-Hulud incident if two or more of the following occur within a single CI run:
- npm lifecycle script execution
- Credential file access
- GitHub repository creation
- npm publish execution
- Cloud secret API access
- Shai-Hulud artifact creation
This pattern strongly indicates autonomous propagation rather than accidental misconfiguration.
Final Assessment
Shai-Hulud represents a structural failure of trust, not a bug in npm.
It demonstrates that modern supply chain attacks no longer require zero-days or registry compromise. They only require:
- A developer
- A token
- A lifecycle hook
Organizations that treat package installation as a “safe” operation are operating on outdated assumptions.
