On September 16, 2025, malicious versions of multiple popular packages were published to npm. They contained a post-install script that harvested sensitive data and exfiltrated it to attacker-created public GitHub repos named Shai-Hulud. Beyond data theft, the malware exhibits worm-like behaviour: when a compromised package encounters additional npm tokens in its environment, it will automatically publish malicious versions of any packages it can access - spreading across the npm ecosystem. Wiz Research assesses this campaign is directly downstream of the late-August 2025 s1ngularity/Nx compromise (initial GitHub token theft to npm token theft to mass package poisoning). As the first successful self-propagating attack in the npm ecosystem, this appears to be one of the most severe JavaScript supply-chain attacks observed to date.
What happened?
Once a version of one of the malicious packages is installed, the included payload uses the TruffleHog secret scanning tool to identify secrets, in addition to harvesting environment variables and IMDS-exposed cloud keys when available.
Additionally, the script validates collected credentials and, if it finds GitHub tokens, it abuses them in multiple ways:
It creates a public repository named Shai-Hulud containing a dump of harvested secrets
It pushes a new GitHub Actions workflow to all accessible repositories. This action exfiltrates each repo’s secrets to
https://webhook[.]site/bb8ca5f6-4175-45d2-b042-fc9ebb8170b7
. It migrates private organizational repositories to public personal repositories under the attacker-controlled user (private org/repo → public user/repo) with the description “Shai-Hulud Migration”, and a-migration
suffix added to the name.
This attack is a self-propagating worm. When a compromised package encounters additional npm tokens in a victim environment, it will automatically publish malicious versions of any packages it can access. See further discussion of the malicious code in Socket's initial analysis.
Based on victimology, Wiz Research assesses this activity is tied to the recent s1ngularity / Nx supply chain attack, where initial GitHub token theft enabled the broader chain of compromise and leaking of formerly private repositories. The initial npm packages that started this chain reaction included multiple known-compromised victims of the s1ngularity attack.
What was the impact?
The attacker exfiltrated data using webhook[.]site
within a malicious GitHub Action. However, under the free plan used, the webhook can only receive a total of 100 callbacks. We observed that the webhook had been deactivated by the platform for excessive activity. This renders the webhook based exfiltration non-functional. However, secrets will still be exposed in the workflow log on GitHub.
Wiz Research initially observed 36 GitHub users with secrets exposed in the “Shai-Hulud” repo (data.json
, double–base64 encoded) and 8 users whose private repositories were force-migrated to public with the label “Shai-Hulud Migration.”
Tracking down repositories with the malicious workflow proved challenging, since GitHub doesn't index deleted branches, commits, or file contents. Still, we were able to uncover 64 additional repositories where a shai-hulud
branch had been created, and in most of them, we found a commit containing the malicious workflow. In many cases, the workflow logs exposed sensitive secrets like GitHub tokens, NPM credentials, Atlassian keys, and Datadog API keys. These are still accessible as of writing this blog.
Despite the clear propagation of the worm to additional npm packages, we have not currently observed the creation of further repositories.
Which actions should security teams take?
Immediate Remediation
Remove malicious versions (
rm -rf node_modules && npm cache clean --force
). See Appendix: Impacted Packages for a point-in-time list of known malicious packages from this attackUpgrade to a clean release (many of the malicious versions have been removed from npm, but as this is still unfolding it is advised to stay vigilant).
Audit & Detection
Check for any evidence of GitHub repos created within your organization’s developers private accounts and user accounts, named Shai-Hulud, or private repositories with the suffix -migration and the description Shai-Hulud Migration.
Use the following Github Query to search for public repositories named Shai-Hulud that were impacted from the first wave of the attack, specifying your org name. Successful compromise would exfiltrate double encoded base64 payload under
data.json
file path with secrets from the affected machine.Use the following Github Query to search for public repositories with the description Shai-Hulud Migration, specifying your org name, that were impacted from the second wave of the attack, successful compromise will result in publication of private repositories publicly, named with a
-mitigation
suffix.Review GitHub audit logs for anomalous API usage.
Monitor developer endpoints and CI/CD pipelines for suspicious API calls and unexpected child processes.
Credential Rotation
Revoke and regenerate all GitHub tokens, npm tokens, SSH keys, API keys, and environment variable secrets that may have been leaked in these repositories.
How can Wiz help?
While Wiz Threat Research are still reviewing impact, Wiz customers can use the pre-built query and advisory in the Wiz Threat Center to assess the risk in their environment.
Wiz customers can use the SBOM page to identify malicious versions and packages in their environment.
Wiz Threat Research added YARA-based detection to identify instances of the malicious script in customer environments, which should be treated as evidence of potential compromise of the host
Wiz Defend customers can use Threat Detection rules to identify the malicious behaviors from this attack in their environments.
Appendix: Impacted Packages
@ahmedhfarag/ngx-perfect-scrollbar
@ahmedhfarag/ngx-virtual-scroller
@art-ws/common
@art-ws/config-eslint
@art-ws/config-ts
@art-ws/db-context
@art-ws/di-node
@art-ws/di
@art-ws/eslint
@art-ws/fastify-http-server
@art-ws/http-server
@art-ws/openapi
@art-ws/package-base
@art-ws/prettier
@art-ws/slf
@art-ws/ssl-info
@art-ws/web-app
@crowdstrike/commitlint (8.1.1, 8.1.2)
@crowdstrike/falcon-shoelace (0.4.1, 0.4.2)
@crowdstrike/foundry-js (0.19.1, 0.19.2)
@crowdstrike/glide-core (0.34.2, 0.34.3)
@crowdstrike/logscale-dashboard (1.205.1, 1.205.2)
@crowdstrike/logscale-file-editor (1.205.1, 1.205.2)
@crowdstrike/logscale-parser-edit (1.205.1, 1.205.2)
@crowdstrike/logscale-search (1.205.1, 1.205.2)
@crowdstrike/tailwind-toucan-base (5.0.1, 5.0.2)
@ctrl/deluge (7.2.1, 7.2.2)
@ctrl/golang-template (1.4.2, 1.4.3)
@ctrl/magnet-link (4.0.3, 4.0.4)
@ctrl/ngx-codemirror (7.0.1, 7.0.2)
@ctrl/ngx-csv (6.0.1, 6.0.2)
@ctrl/ngx-emoji-mart (9.2.1, 9.2.2)
@ctrl/ngx-rightclick (4.0.1, 4.0.2)
@ctrl/qbittorrent (9.7.1, 9.7.2)
@ctrl/react-adsense (2.0.1, 2.0.2)
@ctrl/shared-torrent (6.3.1, 6.3.2)
@ctrl/tinycolor (4.1.1, 4.1.2)
@ctrl/torrent-file (4.1.1, 4.1.2)
@ctrl/transmission (7.3.1)
@ctrl/ts-base32 (4.0.1, 4.0.2)
@hestjs/core
@hestjs/cqrs
@hestjs/demo
@hestjs/eslint-config
@hestjs/logger
@hestjs/scalar
@hestjs/validation
@nativescript-community/arraybuffers (1.1.6, 1.1.7, 1.1.8)
@nativescript-community/gesturehandler (2.0.35)
@nativescript-community/perms (3.0.5, 3.0.6, 3.0.7, 3.0.8, 3.0.9)
@nativescript-community/sentry (4.6.43)
@nativescript-community/sqlite (3.5.2, 3.5.3, 3.5.4, 3.5.5)
@nativescript-community/text (1.6.9, 1.6.10, 1.6.11, 1.6.12, 1.6.13)
@nativescript-community/typeorm (0.2.30, 0.2.31, 0.2.32, 0.2.33)
@nativescript-community/ui-collectionview (6.0.6)
@nativescript-community/ui-document-picker (1.1.27, 1.1.28, 13.0.32)
@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)
@teselagen/bio-parsers (0.4.29)
@teselagen/bounce-loader (0.3.16)
@teselagen/file-utils (0.3.21)
@teselagen/liquibase-tools (0.4.1)
@teselagen/ove (0.7.39)
@teselagen/range-utils (0.3.14)
@teselagen/react-list (0.8.19)
@teselagen/react-table (6.10.21)
@teselagen/sequence-utils (0.3.33)
@teselagen/ui (0.9.9)
angulartics2 (14.1.2)
encounter-playground (0.0.4, 0.0.5)
eslint-config-teselagen (6.1.7)
graphql-sequelize-teselagen (5.3.8)
json-rules-engine-simplified (0.2.1, 0.2.3, 0.2.4)
koa2-swagger-ui (5.11.1, 5.11.2)
ng2-file-upload (8.0.3)
ngx-bootstrap (18.1.4, 19.0.3, 20.0.4, 20.0.5, 20.0.6)
ngx-color (10.0.2)
ngx-toastr (19.0.2)
ngx-trend (8.0.1)
oradm-to-gql (35.0.14)
oradm-to-sqlz (1.1.4)
ove-auto-annotate (0.0.9)
react-complaint-image (0.0.34, 0.0.35)
react-jsonschema-form-conditionals (0.3.20, 0.3.21)
react-jsonschema-form-extras (1.0.3, 1.0.4)
react-jsonschema-rxnt-extras (0.4.8)
rxnt-authentication (0.0.5, 0.0.6)
rxnt-healthchecks-nestjs (1.0.4, 1.0.5)
rxnt-kue (1.0.6, 1.0.7)
swc-plugin-component-annotate (1.9.2)
tg-client-query-builder (2.14.4)
tg-redbird (1.3.1)
tg-seq-gen (1.0.9)
ts-gaussian (3.0.6)
ve-bamreader (0.2.6)
ve-editor (1.0.1)