Multiple CrowdStrike npm packages published by the crowdstrike-publisher npm account were compromised. This looks like a continuation of the ongoing malicious supply chain campaign known as the “Shai-Halud attack” that previously compromised tinycolor and 40+ other packages . The malware is identical to this previous campaign, which includes a bundle.js script that:
Downloads and executes TruffleHog, a legitimate secret scanner Searches host systems for tokens and cloud credentials Validates discovered developer and CI credentials Creates unauthorized GitHub Actions workflows within repositories Exfiltrates sensitive data to a hardcoded webhook endpoint The affected packages were quickly removed by the npm registry. The malware includes a workflow file named shai-hulud.yaml, a nod to the sandworms in Dune . While not a unique reference, its presence reinforces that the attacker deliberately branded the campaign “Shai-Hulud.”
In our previous analysis we found the payload writes a GitHub Actions workflow file named shai-hulud-workflow.yml. Around the same time, nearly 700 public repositories titled “ Shai-Hulud Migration” appeared on GitHub. While the precise role of these repos is still under investigation, their naming and timing suggest they may be artifacts of attacker automation used to persist or stage the workflow. We will update the post as we know more.
Our previous post has further details on the malware itself. The bash block uses a GitHub personal access token if present, writes a GitHub Actions workflow into .github/workflows , and exfiltrates collected content to a webhook.
The script combines local scanning with service specific probing. It looks for environment variables such as GITHUB_TOKEN , NPM_TOKEN , AWS_ACCESS_KEY_ID , and AWS_SECRET_ACCESS_KEY . It validates npm tokens with the whoami endpoint, and it interacts with GitHub APIs when a token is available. It also attempts cloud metadata discovery that can leak short lived credentials inside cloud build agents.
The workflow that it writes to repositories persists beyond the initial host. Once committed, any future CI run can trigger the exfiltration step from within the pipeline where sensitive secrets and artifacts are available by design.
Compromised Packages and Versions# The following npm packages and versions have been confirmed as affected:
@ahmedhfarag/ngx-perfect-scrollbar@20.0.20@ahmedhfarag/ngx-virtual-scroller@4.0.4@art-ws/common@2.0.28@art-ws/config-eslint@2.0.4@art-ws/config-eslint@2.0.5@art-ws/config-ts@2.0.7@art-ws/config-ts@2.0.8@art-ws/db-context@2.0.24@art-ws/di-node@2.0.13@art-ws/di@2.0.28@art-ws/di@2.0.32@art-ws/eslint@1.0.5@art-ws/eslint@1.0.6@art-ws/fastify-http-server@2.0.24@art-ws/fastify-http-server@2.0.27@art-ws/http-server@2.0.21@art-ws/http-server@2.0.25@art-ws/openapi@0.1.12@art-ws/openapi@0.1.9@art-ws/package-base@1.0.5@art-ws/package-base@1.0.6@art-ws/prettier@1.0.5@art-ws/prettier@1.0.6@art-ws/slf@2.0.15@art-ws/slf@2.0.22@art-ws/ssl-info@1.0.10@art-ws/ssl-info@1.0.9@art-ws/web-app@1.0.3@art-ws/web-app@1.0.4@crowdstrike/commitlint@8.1.1@crowdstrike/commitlint@8.1.2@crowdstrike/falcon-shoelace@0.4.1@crowdstrike/falcon-shoelace@0.4.2@crowdstrike/foundry-js@0.19.1@crowdstrike/foundry-js@0.19.2@crowdstrike/glide-core@0.34.2@crowdstrike/glide-core@0.34.3@crowdstrike/logscale-dashboard@1.205.1@crowdstrike/logscale-dashboard@1.205.2@crowdstrike/logscale-file-editor@1.205.1@crowdstrike/logscale-file-editor@1.205.2@crowdstrike/logscale-parser-edit@1.205.1@crowdstrike/logscale-parser-edit@1.205.2@crowdstrike/logscale-search@1.205.1@crowdstrike/logscale-search@1.205.2@crowdstrike/tailwind-toucan-base@5.0.1@crowdstrike/tailwind-toucan-base@5.0.2@ctrl/deluge@7.2.1@ctrl/deluge@7.2.2@ctrl/golang-template@1.4.2@ctrl/golang-template@1.4.3@ctrl/magnet-link@4.0.3@ctrl/magnet-link@4.0.4@ctrl/ngx-codemirror@7.0.1@ctrl/ngx-codemirror@7.0.2@ctrl/ngx-csv@6.0.1@ctrl/ngx-csv@6.0.2@ctrl/ngx-emoji-mart@9.2.1@ctrl/ngx-emoji-mart@9.2.2@ctrl/ngx-rightclick@4.0.1@ctrl/ngx-rightclick@4.0.2@ctrl/qbittorrent@9.7.1@ctrl/qbittorrent@9.7.2@ctrl/react-adsense@2.0.1@ctrl/react-adsense@2.0.2@ctrl/shared-torrent@6.3.1@ctrl/shared-torrent@6.3.2@ctrl/tinycolor@4.1.1@ctrl/tinycolor@4.1.2@ctrl/torrent-file@4.1.1@ctrl/torrent-file@4.1.2@ctrl/transmission@7.3.1@ctrl/ts-base32@4.0.1@ctrl/ts-base32@4.0.2@hestjs/core@0.2.1@hestjs/cqrs@0.1.6@hestjs/demo@0.1.2@hestjs/eslint-config@0.1.2@hestjs/logger@0.1.6@hestjs/scalar@0.1.7@hestjs/validation@0.1.6@nativescript-community/arraybuffers@1.1.6@nativescript-community/arraybuffers@1.1.7@nativescript-community/arraybuffers@1.1.8@nativescript-community/gesturehandler@2.0.35@nativescript-community/perms@3.0.5@nativescript-community/perms@3.0.6@nativescript-community/perms@3.0.7@nativescript-community/perms@3.0.8@nativescript-community/sentry@4.6.43@nativescript-community/sqlite@3.5.2@nativescript-community/sqlite@3.5.3@nativescript-community/sqlite@3.5.4@nativescript-community/sqlite@3.5.5@nativescript-community/text@1.6.10@nativescript-community/text@1.6.11@nativescript-community/text@1.6.12@nativescript-community/text@1.6.13@nativescript-community/text@1.6.9 @nativescript-community/typeorm@0.2.30 @nativescript-community/typeorm@0.2.31 @nativescript-community/typeorm@0.2.32@nativescript-community/typeorm@0.2.33@nativescript-community/ui-collectionview@6.0.6@nativescript-community/ui-document-picker@1.1.27@nativescript-community/ui-document-picker@1.1.28@nativescript-community/ui-drawer@0.1.30@nativescript-community/ui-image@4.5.6@nativescript-community/ui-label@1.3.35@nativescript-community/ui-label@1.3.36@nativescript-community/ui-label@1.3.37@nativescript-community/ui-material-bottom-navigation@7.2.72@nativescript-community/ui-material-bottom-navigation@7.2.73@nativescript-community/ui-material-bottom-navigation@7.2.74@nativescript-community/ui-material-bottom-navigation@7.2.75@nativescript-community/ui-material-bottomsheet@7.2.72@nativescript-community/ui-material-core-tabs@7.2.72@nativescript-community/ui-material-core-tabs@7.2.73@nativescript-community/ui-material-core-tabs@7.2.74@nativescript-community/ui-material-core-tabs@7.2.75@nativescript-community/ui-material-core-tabs@7.2.76@nativescript-community/ui-material-core@7.2.72@nativescript-community/ui-material-core@7.2.73@nativescript-community/ui-material-core@7.2.74@nativescript-community/ui-material-core@7.2.75@nativescript-community/ui-material-core@7.2.76@nativescript-community/ui-material-ripple@7.2.72@nativescript-community/ui-material-ripple@7.2.73@nativescript-community/ui-material-ripple@7.2.74@nativescript-community/ui-material-ripple@7.2.75@nativescript-community/ui-material-tabs@7.2.72@nativescript-community/ui-material-tabs@7.2.73@nativescript-community/ui-material-tabs@7.2.74@nativescript-community/ui-material-tabs@7.2.75@nativescript-community/ui-pager@14.1.36@nativescript-community/ui-pager@14.1.37@nativescript-community/ui-pager@14.1.38@nativescript-community/ui-pulltorefresh@2.5.4@nativescript-community/ui-pulltorefresh@2.5.5@nativescript-community/ui-pulltorefresh@2.5.6@nativescript-community/ui-pulltorefresh@2.5.7@nexe/config-manager@0.1.1@nexe/eslint-config@0.1.1@nexe/logger@0.1.3@nstudio/angular@20.0.4@nstudio/angular@20.0.5@nstudio/angular@20.0.6@nstudio/focus@20.0.4@nstudio/focus@20.0.5@nstudio/focus@20.0.6@nstudio/nativescript-checkbox@2.0.6@nstudio/nativescript-checkbox@2.0.7@nstudio/nativescript-checkbox@2.0.8@nstudio/nativescript-checkbox@2.0.9@nstudio/nativescript-loading-indicator@5.0.1@nstudio/nativescript-loading-indicator@5.0.2@nstudio/nativescript-loading-indicator@5.0.3@nstudio/nativescript-loading-indicator@5.0.4@nstudio/ui-collectionview@5.1.11@nstudio/ui-collectionview@5.1.12@nstudio/ui-collectionview@5.1.13@nstudio/ui-collectionview@5.1.14@nstudio/web-angular@20.0.4@nstudio/web@20.0.4@nstudio/xplat-utils@20.0.5@nstudio/xplat-utils@20.0.6@nstudio/xplat-utils@20.0.7@nstudio/xplat@20.0.5@nstudio/xplat@20.0.6@nstudio/xplat@20.0.7@operato/board@9.0.36@operato/board@9.0.37@operato/board@9.0.38@operato/board@9.0.39@operato/board@9.0.40@operato/board@9.0.41@operato/board@9.0.42@operato/board@9.0.43@operato/board@9.0.44@operato/board@9.0.45@operato/board@9.0.46@operato/data-grist@9.0.29@operato/data-grist@9.0.35@operato/data-grist@9.0.36@operato/data-grist@9.0.37@operato/graphql@9.0.22@operato/graphql@9.0.35@operato/graphql@9.0.36@operato/graphql@9.0.37@operato/graphql@9.0.38@operato/graphql@9.0.39@operato/graphql@9.0.40@operato/graphql@9.0.41@operato/graphql@9.0.42@operato/graphql@9.0.43@operato/graphql@9.0.44@operato/graphql@9.0.45@operato/graphql@9.0.46@operato/headroom@9.0.2@operato/headroom@9.0.35@operato/headroom@9.0.36@operato/headroom@9.0.37@operato/help@9.0.35@operato/help@9.0.36@operato/help@9.0.37@operato/help@9.0.38@operato/help@9.0.39@operato/help@9.0.40@operato/help@9.0.41@operato/help@9.0.42@operato/help@9.0.43@operato/help@9.0.44@operato/help@9.0.45@operato/help@9.0.46@operato/i18n@9.0.35@operato/i18n@9.0.36@operato/i18n@9.0.37@operato/input@9.0.27@operato/input@9.0.35@operato/input@9.0.36@operato/input@9.0.37@operato/input@9.0.38@operato/input@9.0.39@operato/input@9.0.40@operato/input@9.0.41@operato/input@9.0.42@operato/input@9.0.43@operato/input@9.0.44@operato/input@9.0.45@operato/input@9.0.46@operato/input@9.0.47@operato/input@9.0.48@operato/layout@9.0.35@operato/layout@9.0.36@operato/layout@9.0.37@operato/popup@9.0.22@operato/popup@9.0.35@operato/popup@9.0.36@operato/popup@9.0.37@operato/popup@9.0.38@operato/popup@9.0.39@operato/popup@9.0.40@operato/popup@9.0.41@operato/popup@9.0.42@operato/popup@9.0.43@operato/popup@9.0.44@operato/popup@9.0.45@operato/popup@9.0.46@operato/popup@9.0.49@operato/pull-to-refresh@9.0.36@operato/pull-to-refresh@9.0.37@operato/pull-to-refresh@9.0.38@operato/pull-to-refresh@9.0.39@operato/pull-to-refresh@9.0.40@operato/pull-to-refresh@9.0.41@operato/pull-to-refresh@9.0.42@operato/shell@9.0.22@operato/shell@9.0.35@operato/shell@9.0.36@operato/shell@9.0.37@operato/shell@9.0.38@operato/shell@9.0.39@operato/styles@9.0.2@operato/styles@9.0.35@operato/styles@9.0.36@operato/styles@9.0.37@operato/utils@9.0.22@operato/utils@9.0.35@operato/utils@9.0.36@operato/utils@9.0.37@operato/utils@9.0.38@operato/utils@9.0.39@operato/utils@9.0.40@operato/utils@9.0.41@operato/utils@9.0.42@operato/utils@9.0.43@operato/utils@9.0.44@operato/utils@9.0.45@operato/utils@9.0.46@operato/utils@9.0.49@teselagen/bio-parsers@0.4.30@teselagen/bounce-loader@0.3.16@teselagen/bounce-loader@0.3.17@teselagen/file-utils@0.3.22@teselagen/liquibase-tools@0.4.1@teselagen/ove@0.7.40@teselagen/range-utils@0.3.14@teselagen/range-utils@0.3.15@teselagen/react-list@0.8.19@teselagen/react-list@0.8.20@teselagen/react-table@6.10.19@teselagen/react-table@6.10.20@teselagen/react-table@6.10.22@teselagen/sequence-utils@0.3.34@teselagen/ui@0.9.10@thangved/callback-window@1.1.4@things-factory/attachment-base@9.0.43@things-factory/attachment-base@9.0.44@things-factory/attachment-base@9.0.45@things-factory/attachment-base@9.0.46@things-factory/attachment-base@9.0.47@things-factory/attachment-base@9.0.48@things-factory/attachment-base@9.0.49@things-factory/attachment-base@9.0.50@things-factory/auth-base@9.0.43@things-factory/auth-base@9.0.44@things-factory/auth-base@9.0.45@things-factory/email-base@9.0.42@things-factory/email-base@9.0.43@things-factory/email-base@9.0.44@things-factory/email-base@9.0.45@things-factory/email-base@9.0.46@things-factory/email-base@9.0.47@things-factory/email-base@9.0.48@things-factory/email-base@9.0.49@things-factory/email-base@9.0.50@things-factory/email-base@9.0.51@things-factory/email-base@9.0.52@things-factory/email-base@9.0.53@things-factory/email-base@9.0.54@things-factory/env@9.0.42@things-factory/env@9.0.43@things-factory/env@9.0.44@things-factory/env@9.0.45@things-factory/integration-base@9.0.43@things-factory/integration-base@9.0.44@things-factory/integration-base@9.0.45@things-factory/integration-marketplace@9.0.43@things-factory/integration-marketplace@9.0.44@things-factory/integration-marketplace@9.0.45@things-factory/shell@9.0.43@things-factory/shell@9.0.44@things-factory/shell@9.0.45@tnf-dev/api@1.0.8@tnf-dev/core@1.0.8@tnf-dev/js@1.0.8@tnf-dev/mui@1.0.8@tnf-dev/react@1.0.8@ui-ux-gang/devextreme-angular-rpk@24.1.7@yoobic/design-system@6.5.17@yoobic/jpeg-camera-es6@1.0.13@yoobic/yobi@8.7.53airchief@0.3.1airpilot@0.8.8angulartics2@14.1.1angulartics2@14.1.2browser-webdriver-downloader@3.0.8capacitor-notificationhandler@0.0.2capacitor-notificationhandler@0.0.3capacitor-plugin-healthapp@0.0.2capacitor-plugin-healthapp@0.0.3capacitor-plugin-ihealth@1.1.8capacitor-plugin-ihealth@1.1.9capacitor-plugin-vonage@1.0.2capacitor-plugin-vonage@1.0.3capacitorandroidpermissions@0.0.4capacitorandroidpermissions@0.0.5config-cordova@0.8.5cordova-plugin-voxeet2@1.0.24cordova-voxeet@1.0.32create-hest-app@0.1.9db-evo@1.1.4db-evo@1.1.5devextreme-angular-rpk@21.2.8ember-browser-services@5.0.2ember-browser-services@5.0.3ember-headless-form-yup@1.0.1ember-headless-form@1.1.2ember-headless-form@1.1.3ember-headless-table@2.1.5ember-headless-table@2.1.6ember-url-hash-polyfill@1.0.12ember-url-hash-polyfill@1.0.13ember-velcro@2.2.1ember-velcro@2.2.2encounter-playground@0.0.2encounter-playground@0.0.3encounter-playground@0.0.4encounter-playground@0.0.5eslint-config-crowdstrike-node@4.0.3eslint-config-crowdstrike-node@4.0.4eslint-config-crowdstrike@11.0.2eslint-config-crowdstrike@11.0.3eslint-config-teselagen@6.1.7eslint-config-teselagen@6.1.8globalize-rpk@1.7.4graphql-sequelize-teselagen@5.3.8graphql-sequelize-teselagen@5.3.9html-to-base64-image@1.0.2json-rules-engine-simplified@0.2.1json-rules-engine-simplified@0.2.4jumpgate@0.0.2koa2-swagger-ui@5.11.1koa2-swagger-ui@5.11.2mcfly-semantic-release@1.3.1mcp-knowledge-base@0.0.2mcp-knowledge-graph@1.2.1mobioffice-cli@1.0.3monorepo-next@13.0.1monorepo-next@13.0.2mstate-angular@0.4.4mstate-cli@0.4.7mstate-dev-react@1.1.1mstate-react@1.6.5ng2-file-upload@7.0.2ng2-file-upload@7.0.3ng2-file-upload@8.0.1ng2-file-upload@8.0.2ng2-file-upload@8.0.3ng2-file-upload@9.0.1ngx-bootstrap@18.1.4ngx-bootstrap@19.0.3ngx-bootstrap@19.0.4ngx-bootstrap@20.0.3ngx-bootstrap@20.0.4ngx-bootstrap@20.0.5ngx-color@10.0.1ngx-color@10.0.2ngx-toastr@19.0.1ngx-toastr@19.0.2ngx-trend@8.0.1ngx-ws@1.1.5ngx-ws@1.1.6oradm-to-gql@35.0.14oradm-to-gql@35.0.15oradm-to-sqlz@1.1.2ove-auto-annotate@0.0.10ove-auto-annotate@0.0.9pm2-gelf-json@1.0.4pm2-gelf-json@1.0.5printjs-rpk@1.6.1react-complaint-image@0.0.32react-complaint-image@0.0.35react-jsonschema-form-conditionals@0.3.18react-jsonschema-form-conditionals@0.3.21react-jsonschema-form-extras@1.0.4react-jsonschema-rxnt-extras@0.4.9remark-preset-lint-crowdstrike@4.0.1remark-preset-lint-crowdstrike@4.0.2rxnt-authentication@0.0.3rxnt-authentication@0.0.4rxnt-authentication@0.0.5rxnt-authentication@0.0.6rxnt-healthchecks-nestjs@1.0.2rxnt-healthchecks-nestjs@1.0.3rxnt-healthchecks-nestjs@1.0.4rxnt-healthchecks-nestjs@1.0.5rxnt-kue@1.0.4rxnt-kue@1.0.5rxnt-kue@1.0.6rxnt-kue@1.0.7swc-plugin-component-annotate@1.9.1swc-plugin-component-annotate@1.9.2tbssnch@1.0.2teselagen-interval-tree@1.1.2tg-client-query-builder@2.14.4tg-client-query-builder@2.14.5tg-redbird@1.3.1tg-redbird@1.3.2tg-seq-gen@1.0.10tg-seq-gen@1.0.9thangved-react-grid@1.0.3ts-gaussian@3.0.5ts-gaussian@3.0.6ts-imports@1.0.1ts-imports@1.0.2tvi-cli@0.1.5ve-bamreader@0.2.6ve-bamreader@0.2.7ve-editor@1.0.1ve-editor@1.0.2verror-extra@6.0.1voip-callkit@1.0.2voip-callkit@1.0.3wdio-web-reporter@0.1.3yargs-help-output@5.0.3yoo-styles@6.0.326The attack surface is growing and we will continue updating this list.
Uninstall or pin to known-good versions until patched releases are verified.Audit environments (CI/CD agents, developer laptops) that installed the affected versions for unauthorized publishes or credential theft.Rotate npm tokens and other exposed secrets if these packages were present on machines with publishing credentials.Monitor logs for unusual npm publish or package modification events. A full technical analysis of the malware, its propagation method, and remediation guidance will follow as our investigation progresses.
Timeline# All times are npm publishing times in 24-hour UTC.
September 14, 2025 17:58 first observed compromise
rxnt-authentication@0.0.3 (17:58:50)json-rules-engine-simplified@0.2.1 (17:58:51)react-jsonschema-form-conditionals@0.3.18 (17:58:52)encounter-playground@0.0.2 (17:58:52)rxnt-healthchecks-nestjs@1.0.2 (17:58:53)rxnt-kue@1.0.4 (17:58:54)react-complaint-image (17:58:02) Hash for this batch: de0e25a3e6c1e1e5998b306b7141b3dc4c0088da9d7bb47c1c00c91e6e4f85d618:35 small burst
Hash: 81d2a004a1bca6ef87a1caf7d0e0b355ad1764238e40ff6d1b1cb77ad4f595c3
20:29–20:45 first large burst (25+ packages)
Hash: 83a650ce44b2a9854802a7fb4c202877815274c129af49e6c2d1d5d5d55c501e
21:01–21:03 burst (~17 packages)
Hash: 4b2399646573bb737c4969563303d8ee2e9ddbd1b271f1ca9e35ea78062538db
September 15, 2025 01:12 burst (~10 packages)
Hash unchanged from 21:01 group: 4b2399646573bb737c4969563303d8ee2e9ddbd1b271f1ca9e35ea78062538db
02:11 new hash appears, reused across multiple bursts
Hash: dc67467a39b70d1cd4c1f7f7a459b35058163592f4a9e8fb4dffcbba98ef210c
Observed reuse at: 04:58, 05:21, 07:43, 08:21, 08:58, 09:16, 10:41, 13:14, and the next day at 07:41
Impact: more than 100 packages across these bursts (especially at 09:16 and 10:41)
15:35 new hash becomes active for the rest of the day
Hash: 46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09
Bursts observed at: 19:52, 20:23, 22:35, 23:43
Impact: more than 50 packages
September 16, 2025 01:14 first batch of the day (CrowdStrike set)
Hash: b74caeaa75e077c99f7d44f46daaf9796a3be43ecf24f2a1fd381844669da777
Impact: largest single burst, nearly 100 packages
02:32 additional burst (~20 packages)
Hash: b74caeaa75e077c99f7d44f46daaf9796a3be43ecf24f2a1fd381844669da777
03:18 previous day’s hash returns
Hash: 46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09
Impact: ~20 packages at 03:18, ~10 around 05:32, ~60 between 06:17 and 07:11 (many under @operato)
07:41 earlier hash from the 15th reappears
Hash: dc67467a39b70d1cd4c1f7f7a459b35058163592f4a9e8fb4dffcbba98ef210c
Impact: additional handful of packages
10:57–11:09 more @operato packages
Hash: 46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09
Indicators of Compromise# bundle.js SHA-256: 46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09Exfiltration endpoint: hxxps://webhook[.]site/bb8ca5f6-4175-45d2-b042-fc9ebb8170b7 de0e25a3e6c1e1e5998b306b7141b3dc4c0088da9d7bb47c1c00c91e6e4f85d681d2a004a1bca6ef87a1caf7d0e0b355ad1764238e40ff6d1b1cb77ad4f595c383a650ce44b2a9854802a7fb4c202877815274c129af49e6c2d1d5d5d55c501e4b2399646573bb737c4969563303d8ee2e9ddbd1b271f1ca9e35ea78062538dbdc67467a39b70d1cd4c1f7f7a459b35058163592f4a9e8fb4dffcbba98ef210c46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09b74caeaa75e077c99f7d44f46daaf9796a3be43ecf24f2a1fd381844669da777