Original Shai-Hulud npm worm
First successful self-propagating worm in the npm ecosystem. Downstream of the August 2025 s1ngularity/Nx GitHub-token theft. The postinstall hook ran TruffleHog to harvest secrets, opened public GitHub repos named "Shai-Hulud" to publish them, force-converted private repos to public with a "-migration" suffix, and used stolen npm tokens to publish malicious versions of any package the maintainer could access. ~180 unique packages compromised across 300+ versions, including CrowdStrike's own scope (@crowdstrike/*).
- Detected by
- StepSecurity · Socket · Aikido · Wiz
- Also known as
- Shai-Hulud · s1ngularity downstream
- Ecosystems
- npm
- Packages tracked
- 197
What happened
Shai-Hulud is the first publicly-confirmed self-propagating worm in the npm ecosystem. It descends directly from the August 2025 s1ngularity / Nx GitHub-token theft: a researcher leaked Personal Access Tokens from contributors to the nrwl/nx repo, and those tokens were used a month later to seed the worm into reachable maintainer accounts.
The payload runs from a postinstall hook. It uses TruffleHog to scan the host for any credentials it can find - npm tokens, GitHub PATs, AWS/GCP/Azure keys, anything matching a known secret pattern - then performs three propagation moves: it creates a public GitHub repo named "Shai-Hulud" containing the stolen secrets, force-converts private repos belonging to the victim to public with a -migration suffix, and uses the stolen npm tokens to push new malicious versions of every package the maintainer can publish to.
Around 180 unique packages were compromised across 300+ versions before npm and GitHub coordinated takedowns. High-blast-radius hits included @ctrl/tinycolor, ngx-bootstrap, ngx-toastr, and - notably - the entire @crowdstrike/* scope, which forced an internal incident response at CrowdStrike. The worm continued to surface in mini-revivals through early 2026 (see multi-2026-04-30-mini-shai-hulud-wave2 and npm-2026-05-shai-hulud-tanstack).
If you built anything against an affected package between September 15 and 18, 2025, treat the host as credential-compromised: rotate every secret reachable from that environment, then audit the GitHub org for unexpected public repos and -migration twins.
Affected packages (197)
- npm@ahmedhfarag/ngx-perfect-scrollbar20.0.20
- npm@ahmedhfarag/ngx-virtual-scroller4.0.4
- npm@art-ws/common2.0.28
- npm@art-ws/config-eslint2.0.42.0.5
- npm@art-ws/config-ts2.0.72.0.8
- npm@art-ws/db-context2.0.24
- npm@art-ws/di2.0.282.0.32
- npm@art-ws/di-node2.0.13
- npm@art-ws/eslint1.0.51.0.6
- npm@art-ws/fastify-http-server2.0.242.0.27
- npm@art-ws/http-server2.0.212.0.25
- npm@art-ws/openapi0.1.90.1.12
- npm@art-ws/package-base1.0.51.0.6
- npm@art-ws/prettier1.0.51.0.6
- npm@art-ws/slf2.0.152.0.22
- npm@art-ws/ssl-info1.0.91.0.10
- npm@art-ws/web-app1.0.31.0.4
- npm@basic-ui-components-stc/basic-ui-components1.0.5
- npm@crowdstrike/commitlint8.1.18.1.2
- npm@crowdstrike/falcon-shoelace0.4.10.4.2
- npm@crowdstrike/foundry-js0.19.10.19.2
- npm@crowdstrike/glide-core0.34.20.34.3
- npm@crowdstrike/logscale-dashboard1.205.11.205.2
- npm@crowdstrike/logscale-file-editor1.205.11.205.2
- npm@crowdstrike/logscale-parser-edit1.205.11.205.2
- npm@crowdstrike/logscale-search1.205.11.205.2
- npm@crowdstrike/tailwind-toucan-base5.0.15.0.2
- npm@ctrl/deluge7.2.17.2.2
- npm@ctrl/golang-template1.4.21.4.3
- npm@ctrl/magnet-link4.0.34.0.4
- npm@ctrl/ngx-codemirror7.0.17.0.2
- npm@ctrl/ngx-csv6.0.16.0.2
- npm@ctrl/ngx-emoji-mart9.2.19.2.2
- npm@ctrl/ngx-rightclick4.0.14.0.2
- npm@ctrl/qbittorrent9.7.19.7.2
- npm@ctrl/react-adsense2.0.12.0.2
- npm@ctrl/shared-torrent6.3.16.3.2
- npm@ctrl/tinycolor4.1.14.1.2
- npm@ctrl/torrent-file4.1.14.1.2
- npm@ctrl/transmission7.3.1
- npm@ctrl/ts-base324.0.14.0.2
- npm@hestjs/core0.2.1
- npm@hestjs/cqrs0.1.6
- npm@hestjs/demo0.1.2
- npm@hestjs/eslint-config0.1.2
- npm@hestjs/logger0.1.6
- npm@hestjs/scalar0.1.7
- npm@hestjs/validation0.1.6
- npm@nativescript-community/arraybuffers1.1.61.1.71.1.8
- npm@nativescript-community/gesturehandler2.0.35
- npm@nativescript-community/perms3.0.53.0.63.0.73.0.83.0.9
- npm@nativescript-community/sentry4.6.43
- npm@nativescript-community/sqlite3.5.23.5.33.5.43.5.5
- npm@nativescript-community/text1.6.91.6.101.6.111.6.121.6.13
- npm@nativescript-community/typeorm0.2.300.2.310.2.320.2.33
- npm@nativescript-community/ui-collectionview6.0.6
- npm@nativescript-community/ui-document-picker1.1.271.1.2813.0.32
- npm@nativescript-community/ui-drawer0.1.30
- npm@nativescript-community/ui-image4.5.6
- npm@nativescript-community/ui-label1.3.351.3.361.3.37
- npm@nativescript-community/ui-material-bottom-navigation7.2.727.2.737.2.747.2.75
- npm@nativescript-community/ui-material-bottomsheet7.2.72
- npm@nativescript-community/ui-material-core7.2.727.2.737.2.747.2.757.2.76
- npm@nativescript-community/ui-material-core-tabs7.2.727.2.737.2.747.2.757.2.76
- npm@nativescript-community/ui-material-ripple7.2.727.2.737.2.747.2.75
- npm@nativescript-community/ui-material-tabs7.2.727.2.737.2.747.2.75
- npm@nativescript-community/ui-pager14.1.3614.1.3714.1.38
- npm@nativescript-community/ui-pulltorefresh2.5.42.5.52.5.62.5.7
- npm@nexe/config-manager0.1.1
- npm@nexe/eslint-config0.1.1
- npm@nexe/logger0.1.3
- npm@nstudio/angular20.0.420.0.520.0.6
- npm@nstudio/focus20.0.420.0.520.0.6
- npm@nstudio/nativescript-checkbox2.0.62.0.72.0.82.0.9
- npm@nstudio/nativescript-loading-indicator5.0.15.0.25.0.35.0.4
- npm@nstudio/ui-collectionview5.1.115.1.125.1.135.1.14
- npm@nstudio/web20.0.4
- npm@nstudio/web-angular20.0.4
- npm@nstudio/xplat20.0.520.0.620.0.7
- npm@nstudio/xplat-utils20.0.520.0.620.0.7
- npm@operato/board9.0.369.0.379.0.389.0.399.0.409.0.419.0.429.0.439.0.449.0.459.0.46
- npm@operato/data-grist9.0.299.0.359.0.369.0.37
- npm@operato/graphql9.0.229.0.359.0.369.0.379.0.389.0.399.0.409.0.419.0.429.0.439.0.449.0.459.0.46
- npm@operato/headroom9.0.29.0.359.0.369.0.37
- npm@operato/help9.0.359.0.369.0.379.0.389.0.399.0.409.0.419.0.429.0.439.0.449.0.459.0.46
- npm@operato/i18n9.0.359.0.369.0.37
- npm@operato/input9.0.279.0.359.0.369.0.379.0.389.0.399.0.409.0.419.0.429.0.439.0.449.0.459.0.469.0.479.0.48
- npm@operato/layout9.0.359.0.369.0.37
- npm@operato/popup9.0.229.0.359.0.369.0.379.0.389.0.399.0.409.0.419.0.429.0.439.0.449.0.459.0.469.0.49
- npm@operato/pull-to-refresh9.0.369.0.379.0.389.0.399.0.409.0.419.0.42
- npm@operato/shell9.0.229.0.359.0.369.0.379.0.389.0.39
- npm@operato/styles9.0.29.0.359.0.369.0.37
- npm@operato/utils9.0.229.0.359.0.369.0.379.0.389.0.399.0.409.0.419.0.429.0.439.0.449.0.459.0.469.0.49
- npm@teselagen/bio-parsers0.4.290.4.30
- npm@teselagen/bounce-loader0.3.160.3.17
- npm@teselagen/file-utils0.3.210.3.22
- npm@teselagen/liquibase-tools0.4.1
- npm@teselagen/ove0.7.390.7.40
- npm@teselagen/range-utils0.3.140.3.15
- npm@teselagen/react-list0.8.190.8.20
- npm@teselagen/react-table6.10.196.10.206.10.216.10.22
- npm@teselagen/sequence-utils0.3.330.3.34
- npm@teselagen/ui0.9.90.9.10
- npm@thangved/callback-window1.1.4
- npm@things-factory/attachment-base9.0.429.0.439.0.449.0.459.0.469.0.479.0.489.0.499.0.509.0.519.0.529.0.539.0.549.0.55
- npm@things-factory/auth-base9.0.429.0.439.0.449.0.45
- npm@things-factory/email-base9.0.429.0.439.0.449.0.459.0.469.0.479.0.489.0.499.0.509.0.519.0.529.0.539.0.549.0.559.0.569.0.579.0.589.0.59
- npm@things-factory/env9.0.429.0.439.0.449.0.45
- npm@things-factory/integration-base9.0.429.0.439.0.449.0.45
- npm@things-factory/integration-marketplace9.0.429.0.439.0.449.0.45
- npm@things-factory/shell9.0.429.0.439.0.449.0.45
- npm@tnf-dev/api1.0.8
- npm@tnf-dev/core1.0.8
- npm@tnf-dev/js1.0.8
- npm@tnf-dev/mui1.0.8
- npm@tnf-dev/react1.0.8
- npm@ui-ux-gang/devextreme-angular-rpk24.1.7
- npm@yoobic/design-system6.5.17
- npm@yoobic/jpeg-camera-es61.0.13
- npm@yoobic/yobi8.7.53
- npmairchief0.3.1
- npmairpilot0.8.8
- npmangulartics214.1.114.1.2
- npmbrowser-webdriver-downloader3.0.8
- npmcapacitor-notificationhandler0.0.20.0.3
- npmcapacitor-plugin-healthapp0.0.20.0.3
- npmcapacitor-plugin-ihealth1.1.81.1.9
- npmcapacitor-plugin-vonage1.0.21.0.3
- npmcapacitorandroidpermissions0.0.40.0.5
- npmconfig-cordova0.8.5
- npmcordova-plugin-voxeet21.0.24
- npmcordova-voxeet1.0.32
- npmcreate-hest-app0.1.9
- npmdb-evo1.1.41.1.5
- npmdevextreme-angular-rpk21.2.8
- npmdevextreme-rpk21.2.8
- npmember-browser-services5.0.25.0.3
- npmember-headless-form1.1.21.1.3
- npmember-headless-form-yup1.0.1
- npmember-headless-table2.1.52.1.6
- npmember-url-hash-polyfill1.0.121.0.13
- npmember-velcro2.2.12.2.2
- npmencounter-playground0.0.20.0.30.0.40.0.5
- npmeslint-config-crowdstrike11.0.211.0.3
- npmeslint-config-crowdstrike-node4.0.34.0.4
- npmeslint-config-teselagen6.1.76.1.8
- npmglobalize-rpk1.7.4
- npmgraphql-sequelize-teselagen5.3.85.3.9
- npmhtml-to-base64-image1.0.2
- npmjson-rules-engine-simplified0.2.10.2.30.2.4
- npmjumpgate0.0.2
- npmkoa2-swagger-ui5.11.15.11.2
- npmmcfly-semantic-release1.3.1
- npmmcp-knowledge-base0.0.2
- npmmcp-knowledge-graph1.2.1
- npmmobioffice-cli1.0.3
- npmmonorepo-next13.0.113.0.2
- npmmstate-angular0.4.4
- npmmstate-cli0.4.7
- npmmstate-dev-react1.1.1
- npmmstate-react1.6.5
- npmng2-file-upload7.0.27.0.38.0.18.0.28.0.39.0.1
- npmngx-bootstrap18.1.419.0.319.0.420.0.320.0.420.0.520.0.6
- npmngx-color10.0.110.0.2
- npmngx-toastr19.0.119.0.2
- npmngx-trend8.0.1
- npmngx-ws1.1.51.1.6
- npmoradm-to-gql35.0.1435.0.15
- npmoradm-to-sqlz1.1.21.1.4
- npmove-auto-annotate0.0.90.0.10
- npmpm2-gelf-json1.0.41.0.5
- npmprintjs-rpk1.6.1
- npmreact-complaint-image0.0.320.0.340.0.35
- npmreact-jsonschema-form-conditionals0.3.180.3.200.3.21
- npmreact-jsonschema-form-extras1.0.31.0.4
- npmreact-jsonschema-rxnt-extras0.4.80.4.9
- npmremark-preset-lint-crowdstrike4.0.14.0.2
- npmrxnt-authentication0.0.30.0.40.0.50.0.6
- npmrxnt-healthchecks-nestjs1.0.21.0.31.0.41.0.5
- npmrxnt-kue1.0.41.0.51.0.61.0.7
- npmswc-plugin-component-annotate1.9.11.9.2
- npmtbssnch1.0.2
- npmteselagen-interval-tree1.1.2
- npmtg-client-query-builder2.14.42.14.5
- npmtg-redbird1.3.11.3.2
- npmtg-seq-gen1.0.91.0.10
- npmthangved-react-grid1.0.3
- npmts-gaussian3.0.53.0.6
- npmts-imports1.0.11.0.2
- npmtvi-cli0.1.5
- npmve-bamreader0.2.60.2.7
- npmve-editor1.0.11.0.2
- npmverror-extra6.0.1
- npmvoip-callkit1.0.21.0.3
- npmwdio-web-reporter0.1.3
- npmyargs-help-output5.0.3
- npmyoo-styles6.0.326
These are usually pulled in as transitive dependencies rather than installed directly. Check your whole tree at once - it runs in your browser and nothing is uploaded.
Impact
- TruffleHog-driven secret discovery on dev/CI machines
- Public exposure of private repositories ("-migration" rename pattern)
- Stolen-credential propagation to any reachable npm package
- Malicious GitHub Actions workflows for repository-secret exfil
- High-blast-radius packages hit: @ctrl/tinycolor, ngx-bootstrap, ngx-toastr, @crowdstrike/*
What to do
- 1Rotate npm + GitHub tokens used in any environment that resolved affected versions
- 2Audit your GitHub org for public repos created under your account or with "Shai-Hulud" in the name
- 3Review private repos for unexpected "-migration" public twins
- 4Investigate any unexpected publish activity on packages you own
- 5For projects using @crowdstrike/* scopes, treat any host that built after 15 Sept 2025 as suspect until verified