TL;DR
A sophisticated supply chain attack has compromised over 40 NPM packages, including the widely used @ctrl/tinycolor.
The attack leveraged:
- Malicious postinstall scripts that executed obfuscated JavaScript payloads.
- Credential harvesting from environment variables and cloud metadata services.
- Self-propagation by publishing malicious updates to other packages owned by the maintainer.
- GitHub workflow injection that exfiltrated secrets via rogue workflows.
- Persistence mechanisms that survive even after malicious versions were removed from NPM.
This is one of the most advanced NPM ecosystem attacks seen to date.
Attack Overview
1. Initial Compromise
Attackers gained access to an NPM maintainer’s account (notably the popular developer “scttcper”). They then published 41 malicious versions across 38+ packages.
2. Malicious Postinstall Script
Each malicious version contained a postinstall
hook in package.json
that ran a bundled, obfuscated bundle.js
.
3. Reconnaissance & Credential Harvesting
The script attempted to:
- Collect environment variables.
- Probe cloud provider metadata endpoints (AWS, GCP, Azure).
- Run tools like TruffleHog to scrape secrets from local files.
4. Self-Propagation
The malware enumerated packages owned by the compromised maintainer and attempted to publish new malicious versions, spreading the attack further.
5. GitHub Workflow Injection
Using harvested GitHub tokens, a bash script created a new branch shai-hulud
and added a malicious workflow .github/workflows/shai-hulud-workflow.yml
that exfiltrated all secrets from the repository.
6. Persistence
Even if the malicious packages were removed from NPM, the rogue workflows remained active, allowing continued secret exfiltration.
What’s at Stake
- Exposure of GitHub Actions secrets, PATs, API keys.
- Leakage of cloud provider credentials (AWS, GCP, Azure).
- Persistence in repos via injected workflows.
- Potential lateral movement into other packages, repos, or cloud accounts.
Indicators of Compromise (IOCs)
- Branch named
shai-hulud
in your repos. - File:
.github/workflows/shai-hulud-workflow.yml
. - SHA-256 of malicious payload:
46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09
- Unexpected workflow executions sending secrets via
curl
. - Force-published package versions containing
postinstall
scripts.
Full List of Compromised Packages & Versions
The following packages and versions were confirmed compromised:
angulartics2 - 14.1.2
@ctrl/deluge - 7.2.2
@ctrl/golang-template - 1.4.3
@ctrl/magnet-link - 4.0.4
@ctrl/ngx-codemirror - 7.0.2
@ctrl/ngx-csv - 6.0.2
@ctrl/ngx-emoji-mart - 9.2.2
@ctrl/ngx-rightclick - 4.0.2
@ctrl/qbittorrent - 9.7.2
@ctrl/react-adsense - 2.0.2
@ctrl/shared-torrent - 6.3.2
@ctrl/tinycolor - 4.1.1, 4.1.2
@ctrl/torrent-file - 4.1.2
@ctrl/transmission - 7.3.1
@ctrl/ts-base32 - 4.0.2
encounter-playground - 0.0.5
json-rules-engine-simplified - 0.2.4, 0.2.1
koa2-swagger-ui - 5.11.2, 5.11.1
@nativescript-community/gesturehandler - 2.0.35
@nativescript-community/sentry - 4.6.43
@nativescript-community/text -1.6.13
@nativescript-community/ui-collectionview - 6.0.6
@nativescript-community/ui-drawer - 0.1.30
@nativescript-community/ui-image - 4.5.6
@nativescript-community/ui-material-bottomsheet - 7.2.72
@nativescript-community/ui-material-core - 7.2.76
@nativescript-community/ui-material-core-tabs - 7.2.76
ngx-color - 10.0.2
ngx-toastr - 19.0.2
ngx-trend - 8.0.1
react-complaint-image - 0.0.35
react-jsonschema-form-conditionals - 0.3.21
react-jsonschema-form-extras - 1.0.4
rxnt-authentication - 0.0.6
rxnt-healthchecks-nestjs - 1.0.5
rxnt-kue - 1.0.7
swc-plugin-component-annotate - 1.9.2
ts-gaussian - 3.0.6
@crowdstrike/commitlint - 8.1.2
@crowdstrike/falcon-shoelace - 0.4.1
@crowdstrike/foundry-js - 0.19.1.
@crowdstrike/glide-core - 0.34.3
@crowdstrike/logscale-dashboard - 1.205.2
@crowdstrike/logscale-file-editor - 1.205.2
@crowdstrike/logscale-parser-edit - 1.205.2
@crowdstrike/logscale-search - 1.205.2,
@crowdstrike/tailwind-toucan-base - 5.0.2
What To Do Immediately
-
Audit Dependencies
- Search for any of the above packages/versions in your projects.
- Remove or upgrade to clean versions.
-
Inspect Repositories
- Look for the
shai-hulud
branch. - Check
.github/workflows
for unauthorized files.
- Look for the
-
Rotate Secrets
- GitHub tokens, NPM tokens, and cloud credentials must be rotated.
-
Review Logs
- Check for abnormal GitHub workflow runs.
- Audit AWS CloudTrail / GCP / Azure logs for suspicious activity.
-
Harden CI/CD Pipelines
- Enforce branch protection rules.
- Restrict who can create/modify workflows.
- Limit token permissions to least privilege.
Why This Attack Matters
- Wide blast radius: Popular libraries like
@ctrl/tinycolor
were compromised. - Self-propagating: Malicious code spread to other packages by the same maintainer.
- Persistent: Injected workflows survive package removal.
- Deep impact: Exfiltration of GitHub and cloud secrets can cascade into full infrastructure compromise.
Scandog’s Perspective
At Scandog, we see this incident as a pivotal reminder of how fragile the software supply chain can be. Our key takeaways:
- Continuous monitoring of dependencies is essential.
- Workflow integrity must be validated, not assumed.
- Secret management should follow least privilege and regular rotation.
- Incident response readiness is critical when malicious packages slip through.
We are actively assisting organizations in reviewing their dependencies, auditing repositories for rogue workflows, and tightening CI/CD defenses.
Final Thoughts
The Shai-Hulud attack demonstrates how attackers exploit trust in the open-source ecosystem to infiltrate development pipelines at scale.
Organizations need strong supply chain security practices, not just to detect vulnerable code, but to identify malicious behavior in dependencies and CI/CD systems.
Scandog remains committed to helping teams defend against evolving threats like this one.