Skip to content

Instantly share code, notes, and snippets.

@kekru
Last active September 22, 2025 09:08
Show Gist options
  • Save kekru/6017074eaa6aaf08302cd78ef73dc8ca to your computer and use it in GitHub Desktop.
Save kekru/6017074eaa6aaf08302cd78ef73dc8ca to your computer and use it in GitHub Desktop.
Find malicious npm packages in local node_modules folders

Find malicious packages in local node_modules folder and npm registries

In the last few weeks, a few supply chain attacks on widely used npm packages occured.
We often ask ourself, do we have affected versions locally?

Maybe we can trust our anti virus, but maybe not. To be sure, I have written this small script to scan locally for node_modules, and compare against a list of known malicious packages.

WARN: The list of malicious packages is hardcoded in this script!
We will not update this regularly!

But whenever you see some news article about new malicious npm packages, grab this script, paste the new malicious versions from the news article and scan your system

Usage for local scan

Call the script with the folders, that you want to scan.

It will search recursively for package.json files, to find all package.json inside all your nodule_modules.
It only works, if you had run npm install before, to generate the node_modules folder.

It then compares name and version from each **/node_modules/**/package.json against the known malicious versions from inside the script.

node --permission --allow-fs-read c:/ scanNodeModules.mjs "c:/repos, c:/some/where"

Tested with node 22.19. On older version, you might leave out --permission --allow-fs-read c:/

Usage for registry

If you want to check, if your companies npm registry already has a malicious package in its cache, you can run the following

node --permission scanHttpRegistry.mjs https://my-registry.example.com/my/npm

It will run a http head request for each package. If the request returns 404, everything is fine. If it returns 200, it will tell you, that you have a malicious package in the cache.

Beware: If your npm registry is online, this script might load all the malicious packages into your registry!

import fs from 'fs';
/**
* Helps to convert a version.txt into the JSON format, needed for the other scripts
*
* The version.txt must look like this:
*
* @ahmedhfarag/[email protected]
* @ahmedhfarag/[email protected]
* @art-ws/[email protected]
* @art-ws/[email protected]
* [email protected]
* [email protected]
* ...
*/
const content = fs.readFileSync('versions.txt', 'utf8').split('\n');
const out = {}
for (const line of content) {
const name = line.substring(0, line.lastIndexOf('@'));
const version = line.substring(line.lastIndexOf('@') +1);
if (!out[name]) {
out[name] = { versions: [] };
}
out[name].versions.push(version);
}
for (const packageName of Object.keys(out)) {
console.log(` '${packageName}': ${JSON.stringify(out[packageName])},`);
}
if (process.argv.length <= 2) {
console.error(`Usage: node --permission ${process.argv[1]} https://my-registry.example.com/my/npm`);
process.exit(1);
}
const maliciousPackages = {
// https://socket.dev/blog/ongoing-supply-chain-attack-targets-crowdstrike-npm-packages
'@ahmedhfarag/ngx-perfect-scrollbar': {"versions":["20.0.20"]},
'@ahmedhfarag/ngx-virtual-scroller': {"versions":["4.0.4"]},
'@art-ws/common': {"versions":["2.0.28"]},
'@art-ws/config-eslint': {"versions":["2.0.4","2.0.5"]},
'@art-ws/config-ts': {"versions":["2.0.7","2.0.8"]},
'@art-ws/db-context': {"versions":["2.0.24"]},
'@art-ws/di-node': {"versions":["2.0.13"]},
'@art-ws/di': {"versions":["2.0.28","2.0.32"]},
'@art-ws/eslint': {"versions":["1.0.5","1.0.6"]},
'@art-ws/fastify-http-server': {"versions":["2.0.24","2.0.27"]},
'@art-ws/http-server': {"versions":["2.0.21","2.0.25"]},
'@art-ws/openapi': {"versions":["0.1.12","0.1.9"]},
'@art-ws/package-base': {"versions":["1.0.5","1.0.6"]},
'@art-ws/prettier': {"versions":["1.0.5","1.0.6"]},
'@art-ws/slf': {"versions":["2.0.15","2.0.22"]},
'@art-ws/ssl-info': {"versions":["1.0.10","1.0.9"]},
'@art-ws/web-app': {"versions":["1.0.3","1.0.4"]},
'@crowdstrike/commitlint': {"versions":["8.1.1","8.1.2"]},
'@crowdstrike/falcon-shoelace': {"versions":["0.4.1","0.4.2"]},
'@crowdstrike/foundry-js': {"versions":["0.19.1","0.19.2"]},
'@crowdstrike/glide-core': {"versions":["0.34.2","0.34.3"]},
'@crowdstrike/logscale-dashboard': {"versions":["1.205.1","1.205.2"]},
'@crowdstrike/logscale-file-editor': {"versions":["1.205.1","1.205.2"]},
'@crowdstrike/logscale-parser-edit': {"versions":["1.205.1","1.205.2"]},
'@crowdstrike/logscale-search': {"versions":["1.205.1","1.205.2"]},
'@crowdstrike/tailwind-toucan-base': {"versions":["5.0.1","5.0.2"]},
'@ctrl/deluge': {"versions":["7.2.1","7.2.2"]},
'@ctrl/golang-template': {"versions":["1.4.2","1.4.3"]},
'@ctrl/magnet-link': {"versions":["4.0.3","4.0.4"]},
'@ctrl/ngx-codemirror': {"versions":["7.0.1","7.0.2"]},
'@ctrl/ngx-csv': {"versions":["6.0.1","6.0.2"]},
'@ctrl/ngx-emoji-mart': {"versions":["9.2.1","9.2.2"]},
'@ctrl/ngx-rightclick': {"versions":["4.0.1","4.0.2"]},
'@ctrl/qbittorrent': {"versions":["9.7.1","9.7.2"]},
'@ctrl/react-adsense': {"versions":["2.0.1","2.0.2"]},
'@ctrl/shared-torrent': {"versions":["6.3.1","6.3.2"]},
'@ctrl/tinycolor': {"versions":["4.1.1","4.1.2"]},
'@ctrl/torrent-file': {"versions":["4.1.1","4.1.2"]},
'@ctrl/transmission': {"versions":["7.3.1"]},
'@ctrl/ts-base32': {"versions":["4.0.1","4.0.2"]},
'@hestjs/core': {"versions":["0.2.1"]},
'@hestjs/cqrs': {"versions":["0.1.6"]},
'@hestjs/demo': {"versions":["0.1.2"]},
'@hestjs/eslint-config': {"versions":["0.1.2"]},
'@hestjs/logger': {"versions":["0.1.6"]},
'@hestjs/scalar': {"versions":["0.1.7"]},
'@hestjs/validation': {"versions":["0.1.6"]},
'@nativescript-community/arraybuffers': {"versions":["1.1.6","1.1.7","1.1.8"]},
'@nativescript-community/gesturehandler': {"versions":["2.0.35"]},
'@nativescript-community/perms': {"versions":["3.0.5","3.0.6","3.0.7","3.0.8","3.0.9"]},
'@nativescript-community/sentry': {"versions":["4.6.43"]},
'@nativescript-community/sqlite': {"versions":["3.5.2","3.5.3","3.5.4","3.5.5"]},
'@nativescript-community/text': {"versions":["1.6.10","1.6.11","1.6.12","1.6.13","1.6.9"]},
'@nativescript-community/typeorm': {"versions":["0.2.30","0.2.31","0.2.32","0.2.33"]},
'@nativescript-community/ui-collectionview': {"versions":["6.0.6"]},
'@nativescript-community/ui-document-picker': {"versions":["1.1.27","1.1.28"]},
'@nativescript-community/ui-drawer': {"versions":["0.1.30"]},
'@nativescript-community/ui-image': {"versions":["4.5.6"]},
'@nativescript-community/ui-label': {"versions":["1.3.35","1.3.36","1.3.37"]},
'@nativescript-community/ui-material-bottom-navigation': {"versions":["7.2.72","7.2.73","7.2.74","7.2.75"]},
'@nativescript-community/ui-material-bottomsheet': {"versions":["7.2.72"]},
'@nativescript-community/ui-material-core-tabs': {"versions":["7.2.72","7.2.73","7.2.74","7.2.75","7.2.76"]},
'@nativescript-community/ui-material-core': {"versions":["7.2.72","7.2.73","7.2.74","7.2.75","7.2.76"]},
'@nativescript-community/ui-material-ripple': {"versions":["7.2.72","7.2.73","7.2.74","7.2.75"]},
'@nativescript-community/ui-material-tabs': {"versions":["7.2.72","7.2.73","7.2.74","7.2.75"]},
'@nativescript-community/ui-pager': {"versions":["14.1.36","14.1.37","14.1.38"]},
'@nativescript-community/ui-pulltorefresh': {"versions":["2.5.4","2.5.5","2.5.6","2.5.7"]},
'@nexe/config-manager': {"versions":["0.1.1"]},
'@nexe/eslint-config': {"versions":["0.1.1"]},
'@nexe/logger': {"versions":["0.1.3"]},
'@nstudio/angular': {"versions":["20.0.4","20.0.5","20.0.6"]},
'@nstudio/focus': {"versions":["20.0.4","20.0.5","20.0.6"]},
'@nstudio/nativescript-checkbox': {"versions":["2.0.6","2.0.7","2.0.8","2.0.9"]},
'@nstudio/nativescript-loading-indicator': {"versions":["5.0.1","5.0.2","5.0.3","5.0.4"]},
'@nstudio/ui-collectionview': {"versions":["5.1.11","5.1.12","5.1.13","5.1.14"]},
'@nstudio/web-angular': {"versions":["20.0.4"]},
'@nstudio/web': {"versions":["20.0.4"]},
'@nstudio/xplat-utils': {"versions":["20.0.5","20.0.6","20.0.7"]},
'@nstudio/xplat': {"versions":["20.0.5","20.0.6","20.0.7"]},
'@operato/board': {"versions":["9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51"]},
'@operato/data-grist': {"versions":["9.0.29","9.0.35","9.0.36","9.0.37"]},
'@operato/graphql': {"versions":["9.0.22","9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51"]},
'@operato/headroom': {"versions":["9.0.2","9.0.35","9.0.36","9.0.37"]},
'@operato/help': {"versions":["9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51"]},
'@operato/i18n': {"versions":["9.0.35","9.0.36","9.0.37"]},
'@operato/input': {"versions":["9.0.27","9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48"]},
'@operato/layout': {"versions":["9.0.35","9.0.36","9.0.37"]},
'@operato/popup': {"versions":["9.0.22","9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51"]},
'@operato/pull-to-refresh': {"versions":["9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47"]},
'@operato/shell': {"versions":["9.0.22","9.0.35","9.0.36","9.0.37","9.0.38","9.0.39"]},
'@operato/styles': {"versions":["9.0.2","9.0.35","9.0.36","9.0.37"]},
'@operato/utils': {"versions":["9.0.22","9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51"]},
'@rxap/ngx-bootstrap': {"versions":["19.0.3","19.0.4"]},
'@teriyakibomb/ember-velcro': {"versions":["2.2.1"]},
'@teselagen/bio-parsers': {"versions":["0.4.30"]},
'@teselagen/bounce-loader': {"versions":["0.3.16","0.3.17"]},
'@teselagen/file-utils': {"versions":["0.3.22"]},
'@teselagen/liquibase-tools': {"versions":["0.4.1"]},
'@teselagen/ove': {"versions":["0.7.40"]},
'@teselagen/range-utils': {"versions":["0.3.14","0.3.15"]},
'@teselagen/react-list': {"versions":["0.8.19","0.8.20"]},
'@teselagen/react-table': {"versions":["6.10.19","6.10.20","6.10.22"]},
'@teselagen/sequence-utils': {"versions":["0.3.34"]},
'@teselagen/ui': {"versions":["0.9.10"]},
'@thangved/callback-window': {"versions":["1.1.4"]},
'@things-factory/attachment-base': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51","9.0.52","9.0.53","9.0.54","9.0.55"]},
'@things-factory/auth-base': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45"]},
'@things-factory/email-base': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51","9.0.52","9.0.53","9.0.54","9.0.55","9.0.56","9.0.57","9.0.58","9.0.59"]},
'@things-factory/env': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45"]},
'@things-factory/integration-base': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45"]},
'@things-factory/integration-marketplace': {"versions":["9.0.43","9.0.44","9.0.45"]},
'@things-factory/shell': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45"]},
'@tnf-dev/api': {"versions":["1.0.8"]},
'@tnf-dev/core': {"versions":["1.0.8"]},
'@tnf-dev/js': {"versions":["1.0.8"]},
'@tnf-dev/mui': {"versions":["1.0.8"]},
'@tnf-dev/react': {"versions":["1.0.8"]},
'@ui-ux-gang/devextreme-angular-rpk': {"versions":["24.1.7"]},
'@yoobic/design-system': {"versions":["6.5.17"]},
'@yoobic/jpeg-camera-es6': {"versions":["1.0.13"]},
'@yoobic/yobi': {"versions":["8.7.53"]},
'airchief': {"versions":["0.3.1"]},
'airpilot': {"versions":["0.8.8"]},
'angulartics2': {"versions":["14.1.1","14.1.2"]},
'another-shai': {"versions":["1.0.1"]},
'browser-webdriver-downloader': {"versions":["3.0.8"]},
'capacitor-notificationhandler': {"versions":["0.0.2","0.0.3"]},
'capacitor-plugin-healthapp': {"versions":["0.0.2","0.0.3"]},
'capacitor-plugin-ihealth': {"versions":["1.1.8","1.1.9"]},
'capacitor-plugin-vonage': {"versions":["1.0.2","1.0.3"]},
'capacitorandroidpermissions': {"versions":["0.0.4","0.0.5"]},
'config-cordova': {"versions":["0.8.5"]},
'cordova-plugin-voxeet2': {"versions":["1.0.24"]},
'cordova-voxeet': {"versions":["1.0.32"]},
'create-hest-app': {"versions":["0.1.9"]},
'db-evo': {"versions":["1.1.4","1.1.5"]},
'devextreme-angular-rpk': {"versions":["21.2.8"]},
'ember-browser-services': {"versions":["5.0.2","5.0.3"]},
'ember-headless-form-yup': {"versions":["1.0.1"]},
'ember-headless-form': {"versions":["1.1.2","1.1.3"]},
'ember-headless-table': {"versions":["2.1.5","2.1.6"]},
'ember-url-hash-polyfill': {"versions":["1.0.12","1.0.13"]},
'ember-velcro': {"versions":["2.2.1","2.2.2"]},
'encounter-playground': {"versions":["0.0.2","0.0.3","0.0.4","0.0.5"]},
'eslint-config-crowdstrike-node': {"versions":["4.0.3","4.0.4"]},
'eslint-config-crowdstrike': {"versions":["11.0.2","11.0.3"]},
'eslint-config-teselagen': {"versions":["6.1.7","6.1.8"]},
'globalize-rpk': {"versions":["1.7.4"]},
'graphql-sequelize-teselagen': {"versions":["5.3.8","5.3.9"]},
'html-to-base64-image': {"versions":["1.0.2"]},
'json-rules-engine-simplified': {"versions":["0.2.1","0.2.4"]},
'jumpgate': {"versions":["0.0.2"]},
'koa2-swagger-ui': {"versions":["5.11.1","5.11.2"]},
'mcfly-semantic-release': {"versions":["1.3.1"]},
'mcp-knowledge-base': {"versions":["0.0.2"]},
'mcp-knowledge-graph': {"versions":["1.2.1"]},
'mobioffice-cli': {"versions":["1.0.3"]},
'monorepo-next': {"versions":["13.0.1","13.0.2"]},
'mstate-angular': {"versions":["0.4.4"]},
'mstate-cli': {"versions":["0.4.7"]},
'mstate-dev-react': {"versions":["1.1.1"]},
'mstate-react': {"versions":["1.6.5"]},
'ng2-file-upload': {"versions":["7.0.2","7.0.3","8.0.1","8.0.2","8.0.3","9.0.1"]},
'ngx-bootstrap': {"versions":["18.1.4","19.0.3","19.0.4","20.0.3","20.0.4","20.0.5"]},
'ngx-color': {"versions":["10.0.1","10.0.2"]},
'ngx-toastr': {"versions":["19.0.1","19.0.2"]},
'ngx-trend': {"versions":["8.0.1"]},
'ngx-ws': {"versions":["1.1.5","1.1.6"]},
'oradm-to-gql': {"versions":["35.0.14","35.0.15"]},
'oradm-to-sqlz': {"versions":["1.1.2"]},
'ove-auto-annotate': {"versions":["0.0.10","0.0.9"]},
'pm2-gelf-json': {"versions":["1.0.4","1.0.5"]},
'printjs-rpk': {"versions":["1.6.1"]},
'react-complaint-image': {"versions":["0.0.32","0.0.35"]},
'react-jsonschema-form-conditionals': {"versions":["0.3.18","0.3.21"]},
'react-jsonschema-form-extras': {"versions":["1.0.4"]},
'react-jsonschema-rxnt-extras': {"versions":["0.4.9"]},
'remark-preset-lint-crowdstrike': {"versions":["4.0.1","4.0.2"]},
'rxnt-authentication': {"versions":["0.0.3","0.0.4","0.0.5","0.0.6"]},
'rxnt-healthchecks-nestjs': {"versions":["1.0.2","1.0.3","1.0.4","1.0.5"]},
'rxnt-kue': {"versions":["1.0.4","1.0.5","1.0.6","1.0.7"]},
'swc-plugin-component-annotate': {"versions":["1.9.1","1.9.2"]},
'tbssnch': {"versions":["1.0.2"]},
'teselagen-interval-tree': {"versions":["1.1.2"]},
'tg-client-query-builder': {"versions":["2.14.4","2.14.5"]},
'tg-redbird': {"versions":["1.3.1","1.3.2"]},
'tg-seq-gen': {"versions":["1.0.10","1.0.9"]},
'thangved-react-grid': {"versions":["1.0.3"]},
'ts-gaussian': {"versions":["3.0.5","3.0.6"]},
'ts-imports': {"versions":["1.0.1","1.0.2"]},
'tvi-cli': {"versions":["0.1.5"]},
've-bamreader': {"versions":["0.2.6","0.2.7"]},
've-editor': {"versions":["1.0.1","1.0.2"]},
'verror-extra': {"versions":["6.0.1"]},
'voip-callkit': {"versions":["1.0.2","1.0.3"]},
'wdio-web-reporter': {"versions":["0.1.3"]},
'yargs-help-output': {"versions":["5.0.3"]},
'yoo-styles': {"versions":["6.0.326"]},
// https://jfrog.com/blog/new-compromised-packages-in-largest-npm-attack-in-history/
'backslash': { versions: [ '0.2.1' ] },
'chalk-template': { versions: [ '1.1.1' ] },
'supports-hyperlinks': { versions: [ '4.1.1' ] },
'has-ansi': { versions: [ '6.0.1' ] },
'simple-swizzle': { versions: [ '0.2.3' ] },
'color-string': { versions: [ '2.1.1' ] },
'error-ex': { versions: [ '1.3.3' ] },
'color-name': { versions: [ '2.0.1' ] },
'is-arrayish': { versions: [ '0.3.3' ] },
'slice-ansi': { versions: [ '7.1.1' ] },
'color-convert': { versions: [ '3.1.1' ] },
'wrap-ansi': { versions: [ '9.0.1' ] },
'ansi-regex': { versions: [ '6.2.1' ] },
'supports-color': { versions: [ '10.2.1' ] },
'strip-ansi': { versions: [ '7.1.1' ] },
'chalk': { versions: [ '5.6.1' ] },
'debug': { versions: [ '4.4.2' ] },
'ansi-styles': { versions: [ '6.2.2' ] },
'proto-tinker-wc': { versions: [ '0.1.87' ] },
'prebid': { versions: [ '10.9.1', '10.9.2' ] },
'@coveops/abi': { versions: [ '2.0.1' ] },
'duckdb': { versions: [ '1.3.3' ] },
'@duckdb/node-bindings': { versions: [ '1.3.3' ] },
'@duckdb/duckdb-wasm': { versions: [ '1.29.2' ] },
'@duckdb/node-api': { versions: [ '1.3.3' ] },
// https://socket.dev/blog/npm-is-package-hijacked-in-expanding-supply-chain-attack
'eslint-config-prettier': { versions: [ '8.10.1', '9.1.1', '10.1.6', '10.1.7' ] },
'eslint-plugin-prettier': { versions: [ '4.2.2', '4.2.3' ] },
'synckit': { versions: [ '0.11.9' ] },
'@pkgr/core': { versions: [ '0.2.8' ] },
'napi-postinstall': { versions: [ '0.3.1' ] },
'got-fetch': { versions: [ '5.1.11', '5.1.12' ] },
'is': { versions: [ '3.3.1', '5.0.0' ] },
// https://github.com/nrwl/nx/security/advisories/GHSA-cxm3-wv7p-598c
'@nx/devkit': { versions: [ '21.5.0', '20.9.0' ] },
'@nx/enterprise-cloud': { versions: [ '3.2.0' ] },
'@nx/eslint': { versions: [ '21.5.0' ] },
'@nx/js': { versions: [ '21.5.0', '20.9.0' ] },
'@nx/key': { versions: [ '3.2.0' ] },
'@nx/node': { versions: [ '21.5.0', '20.9.0' ] },
'@nx/workspace': { versions: [ '21.5.0', '20.9.0' ] },
'nx': { versions: [ '21.5.0', '20.9.0', '20.10.0', '21.6.0', '20.11.0', '21.7.0', '21.8.0', '20.12.0' ] },
}
const registryBaseUrl = process.argv[2]
await checkLodash(registryBaseUrl)
const foundMaliciousPackageUrls = []
const unknownStatusCodeUrls = []
for (const maliciousPackage in maliciousPackages) {
const packageWithoutPrefix = maliciousPackage.indexOf('/') >= 0
? maliciousPackage.substring(maliciousPackage.indexOf('/') + 1)
: maliciousPackage
for (const version of maliciousPackages[maliciousPackage].versions) {
const url = `${registryBaseUrl}/${maliciousPackage}/-/${packageWithoutPrefix}-${version}.tgz`
const result = await fetch(url, { method: 'HEAD' })
const resultStatus = result.status
if (resultStatus === 404) {
console.log(`Not present ${url} -> ok`)
} else if (resultStatus === 200) {
console.log(`Malicious package found: ${url}`)
foundMaliciousPackageUrls.push(url)
} else {
console.log(`Unknown status code ${resultStatus} for url ${url}`)
unknownStatusCodeUrls.push(url)
}
}
}
if (unknownStatusCodeUrls.length > 0) {
console.log(`Found ${unknownStatusCodeUrls.length} urls with unknown status codes: ${JSON.stringify(unknownStatusCodeUrls, null, 2)}`)
}
if (foundMaliciousPackageUrls.length > 0) {
throw new Error(`Found ${foundMaliciousPackageUrls.length} malicious package urls: ${JSON.stringify(foundMaliciousPackageUrls, null, 2)}`)
} else {
console.log(`No malicious packages found in the registry ${registryBaseUrl}`)
}
async function checkLodash(registryBaseUrl) {
const url = `${registryBaseUrl}/lodash/-/lodash-4.17.21.tgz`
console.log(`Checking if registry ${registryBaseUrl} is reachable by fetching lodash package: ${url}`)
const result = await fetch(url, { method: 'HEAD' })
const resultStatus = result.status
if (resultStatus !== 200) {
throw new Error(`Could not reach the registry ${registryBaseUrl}, got status code ${resultStatus} for url ${url}`)
}
}
import { readFileSync } from 'node:fs';
import { readdir } from 'node:fs/promises';
import path from 'path';
if (process.argv.length <= 2) {
console.error(`Usage: node --permission --allow-fs-read ... ${process.argv[1]} "<directory>,<directory2>,..."`);
console.error(`Example: node --permission --allow-fs-read c:/ ${process.argv[1]} "c:/repos,c:/more/repos"`);
process.exit(1);
}
const scanDirs = process.argv[2].split(',').map(dir => dir.trim());
console.log(`Starting scan for malicious npm packages in the following directories: ${scanDirs.join(', ')}`)
console.log(`Be sure to set node --allow-fs-read=... for all dirs, so nodejs can read it`);
let counter = 0
const maliciousPackages = {
// https://socket.dev/blog/ongoing-supply-chain-attack-targets-crowdstrike-npm-packages
'@ahmedhfarag/ngx-perfect-scrollbar': {"versions":["20.0.20"]},
'@ahmedhfarag/ngx-virtual-scroller': {"versions":["4.0.4"]},
'@art-ws/common': {"versions":["2.0.28"]},
'@art-ws/config-eslint': {"versions":["2.0.4","2.0.5"]},
'@art-ws/config-ts': {"versions":["2.0.7","2.0.8"]},
'@art-ws/db-context': {"versions":["2.0.24"]},
'@art-ws/di-node': {"versions":["2.0.13"]},
'@art-ws/di': {"versions":["2.0.28","2.0.32"]},
'@art-ws/eslint': {"versions":["1.0.5","1.0.6"]},
'@art-ws/fastify-http-server': {"versions":["2.0.24","2.0.27"]},
'@art-ws/http-server': {"versions":["2.0.21","2.0.25"]},
'@art-ws/openapi': {"versions":["0.1.12","0.1.9"]},
'@art-ws/package-base': {"versions":["1.0.5","1.0.6"]},
'@art-ws/prettier': {"versions":["1.0.5","1.0.6"]},
'@art-ws/slf': {"versions":["2.0.15","2.0.22"]},
'@art-ws/ssl-info': {"versions":["1.0.10","1.0.9"]},
'@art-ws/web-app': {"versions":["1.0.3","1.0.4"]},
'@crowdstrike/commitlint': {"versions":["8.1.1","8.1.2"]},
'@crowdstrike/falcon-shoelace': {"versions":["0.4.1","0.4.2"]},
'@crowdstrike/foundry-js': {"versions":["0.19.1","0.19.2"]},
'@crowdstrike/glide-core': {"versions":["0.34.2","0.34.3"]},
'@crowdstrike/logscale-dashboard': {"versions":["1.205.1","1.205.2"]},
'@crowdstrike/logscale-file-editor': {"versions":["1.205.1","1.205.2"]},
'@crowdstrike/logscale-parser-edit': {"versions":["1.205.1","1.205.2"]},
'@crowdstrike/logscale-search': {"versions":["1.205.1","1.205.2"]},
'@crowdstrike/tailwind-toucan-base': {"versions":["5.0.1","5.0.2"]},
'@ctrl/deluge': {"versions":["7.2.1","7.2.2"]},
'@ctrl/golang-template': {"versions":["1.4.2","1.4.3"]},
'@ctrl/magnet-link': {"versions":["4.0.3","4.0.4"]},
'@ctrl/ngx-codemirror': {"versions":["7.0.1","7.0.2"]},
'@ctrl/ngx-csv': {"versions":["6.0.1","6.0.2"]},
'@ctrl/ngx-emoji-mart': {"versions":["9.2.1","9.2.2"]},
'@ctrl/ngx-rightclick': {"versions":["4.0.1","4.0.2"]},
'@ctrl/qbittorrent': {"versions":["9.7.1","9.7.2"]},
'@ctrl/react-adsense': {"versions":["2.0.1","2.0.2"]},
'@ctrl/shared-torrent': {"versions":["6.3.1","6.3.2"]},
'@ctrl/tinycolor': {"versions":["4.1.1","4.1.2"]},
'@ctrl/torrent-file': {"versions":["4.1.1","4.1.2"]},
'@ctrl/transmission': {"versions":["7.3.1"]},
'@ctrl/ts-base32': {"versions":["4.0.1","4.0.2"]},
'@hestjs/core': {"versions":["0.2.1"]},
'@hestjs/cqrs': {"versions":["0.1.6"]},
'@hestjs/demo': {"versions":["0.1.2"]},
'@hestjs/eslint-config': {"versions":["0.1.2"]},
'@hestjs/logger': {"versions":["0.1.6"]},
'@hestjs/scalar': {"versions":["0.1.7"]},
'@hestjs/validation': {"versions":["0.1.6"]},
'@nativescript-community/arraybuffers': {"versions":["1.1.6","1.1.7","1.1.8"]},
'@nativescript-community/gesturehandler': {"versions":["2.0.35"]},
'@nativescript-community/perms': {"versions":["3.0.5","3.0.6","3.0.7","3.0.8","3.0.9"]},
'@nativescript-community/sentry': {"versions":["4.6.43"]},
'@nativescript-community/sqlite': {"versions":["3.5.2","3.5.3","3.5.4","3.5.5"]},
'@nativescript-community/text': {"versions":["1.6.10","1.6.11","1.6.12","1.6.13","1.6.9"]},
'@nativescript-community/typeorm': {"versions":["0.2.30","0.2.31","0.2.32","0.2.33"]},
'@nativescript-community/ui-collectionview': {"versions":["6.0.6"]},
'@nativescript-community/ui-document-picker': {"versions":["1.1.27","1.1.28"]},
'@nativescript-community/ui-drawer': {"versions":["0.1.30"]},
'@nativescript-community/ui-image': {"versions":["4.5.6"]},
'@nativescript-community/ui-label': {"versions":["1.3.35","1.3.36","1.3.37"]},
'@nativescript-community/ui-material-bottom-navigation': {"versions":["7.2.72","7.2.73","7.2.74","7.2.75"]},
'@nativescript-community/ui-material-bottomsheet': {"versions":["7.2.72"]},
'@nativescript-community/ui-material-core-tabs': {"versions":["7.2.72","7.2.73","7.2.74","7.2.75","7.2.76"]},
'@nativescript-community/ui-material-core': {"versions":["7.2.72","7.2.73","7.2.74","7.2.75","7.2.76"]},
'@nativescript-community/ui-material-ripple': {"versions":["7.2.72","7.2.73","7.2.74","7.2.75"]},
'@nativescript-community/ui-material-tabs': {"versions":["7.2.72","7.2.73","7.2.74","7.2.75"]},
'@nativescript-community/ui-pager': {"versions":["14.1.36","14.1.37","14.1.38"]},
'@nativescript-community/ui-pulltorefresh': {"versions":["2.5.4","2.5.5","2.5.6","2.5.7"]},
'@nexe/config-manager': {"versions":["0.1.1"]},
'@nexe/eslint-config': {"versions":["0.1.1"]},
'@nexe/logger': {"versions":["0.1.3"]},
'@nstudio/angular': {"versions":["20.0.4","20.0.5","20.0.6"]},
'@nstudio/focus': {"versions":["20.0.4","20.0.5","20.0.6"]},
'@nstudio/nativescript-checkbox': {"versions":["2.0.6","2.0.7","2.0.8","2.0.9"]},
'@nstudio/nativescript-loading-indicator': {"versions":["5.0.1","5.0.2","5.0.3","5.0.4"]},
'@nstudio/ui-collectionview': {"versions":["5.1.11","5.1.12","5.1.13","5.1.14"]},
'@nstudio/web-angular': {"versions":["20.0.4"]},
'@nstudio/web': {"versions":["20.0.4"]},
'@nstudio/xplat-utils': {"versions":["20.0.5","20.0.6","20.0.7"]},
'@nstudio/xplat': {"versions":["20.0.5","20.0.6","20.0.7"]},
'@operato/board': {"versions":["9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51"]},
'@operato/data-grist': {"versions":["9.0.29","9.0.35","9.0.36","9.0.37"]},
'@operato/graphql': {"versions":["9.0.22","9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51"]},
'@operato/headroom': {"versions":["9.0.2","9.0.35","9.0.36","9.0.37"]},
'@operato/help': {"versions":["9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51"]},
'@operato/i18n': {"versions":["9.0.35","9.0.36","9.0.37"]},
'@operato/input': {"versions":["9.0.27","9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48"]},
'@operato/layout': {"versions":["9.0.35","9.0.36","9.0.37"]},
'@operato/popup': {"versions":["9.0.22","9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51"]},
'@operato/pull-to-refresh': {"versions":["9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47"]},
'@operato/shell': {"versions":["9.0.22","9.0.35","9.0.36","9.0.37","9.0.38","9.0.39"]},
'@operato/styles': {"versions":["9.0.2","9.0.35","9.0.36","9.0.37"]},
'@operato/utils': {"versions":["9.0.22","9.0.35","9.0.36","9.0.37","9.0.38","9.0.39","9.0.40","9.0.41","9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51"]},
'@rxap/ngx-bootstrap': {"versions":["19.0.3","19.0.4"]},
'@teriyakibomb/ember-velcro': {"versions":["2.2.1"]},
'@teselagen/bio-parsers': {"versions":["0.4.30"]},
'@teselagen/bounce-loader': {"versions":["0.3.16","0.3.17"]},
'@teselagen/file-utils': {"versions":["0.3.22"]},
'@teselagen/liquibase-tools': {"versions":["0.4.1"]},
'@teselagen/ove': {"versions":["0.7.40"]},
'@teselagen/range-utils': {"versions":["0.3.14","0.3.15"]},
'@teselagen/react-list': {"versions":["0.8.19","0.8.20"]},
'@teselagen/react-table': {"versions":["6.10.19","6.10.20","6.10.22"]},
'@teselagen/sequence-utils': {"versions":["0.3.34"]},
'@teselagen/ui': {"versions":["0.9.10"]},
'@thangved/callback-window': {"versions":["1.1.4"]},
'@things-factory/attachment-base': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51","9.0.52","9.0.53","9.0.54","9.0.55"]},
'@things-factory/auth-base': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45"]},
'@things-factory/email-base': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45","9.0.46","9.0.47","9.0.48","9.0.49","9.0.50","9.0.51","9.0.52","9.0.53","9.0.54","9.0.55","9.0.56","9.0.57","9.0.58","9.0.59"]},
'@things-factory/env': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45"]},
'@things-factory/integration-base': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45"]},
'@things-factory/integration-marketplace': {"versions":["9.0.43","9.0.44","9.0.45"]},
'@things-factory/shell': {"versions":["9.0.42","9.0.43","9.0.44","9.0.45"]},
'@tnf-dev/api': {"versions":["1.0.8"]},
'@tnf-dev/core': {"versions":["1.0.8"]},
'@tnf-dev/js': {"versions":["1.0.8"]},
'@tnf-dev/mui': {"versions":["1.0.8"]},
'@tnf-dev/react': {"versions":["1.0.8"]},
'@ui-ux-gang/devextreme-angular-rpk': {"versions":["24.1.7"]},
'@yoobic/design-system': {"versions":["6.5.17"]},
'@yoobic/jpeg-camera-es6': {"versions":["1.0.13"]},
'@yoobic/yobi': {"versions":["8.7.53"]},
'airchief': {"versions":["0.3.1"]},
'airpilot': {"versions":["0.8.8"]},
'angulartics2': {"versions":["14.1.1","14.1.2"]},
'another-shai': {"versions":["1.0.1"]},
'browser-webdriver-downloader': {"versions":["3.0.8"]},
'capacitor-notificationhandler': {"versions":["0.0.2","0.0.3"]},
'capacitor-plugin-healthapp': {"versions":["0.0.2","0.0.3"]},
'capacitor-plugin-ihealth': {"versions":["1.1.8","1.1.9"]},
'capacitor-plugin-vonage': {"versions":["1.0.2","1.0.3"]},
'capacitorandroidpermissions': {"versions":["0.0.4","0.0.5"]},
'config-cordova': {"versions":["0.8.5"]},
'cordova-plugin-voxeet2': {"versions":["1.0.24"]},
'cordova-voxeet': {"versions":["1.0.32"]},
'create-hest-app': {"versions":["0.1.9"]},
'db-evo': {"versions":["1.1.4","1.1.5"]},
'devextreme-angular-rpk': {"versions":["21.2.8"]},
'ember-browser-services': {"versions":["5.0.2","5.0.3"]},
'ember-headless-form-yup': {"versions":["1.0.1"]},
'ember-headless-form': {"versions":["1.1.2","1.1.3"]},
'ember-headless-table': {"versions":["2.1.5","2.1.6"]},
'ember-url-hash-polyfill': {"versions":["1.0.12","1.0.13"]},
'ember-velcro': {"versions":["2.2.1","2.2.2"]},
'encounter-playground': {"versions":["0.0.2","0.0.3","0.0.4","0.0.5"]},
'eslint-config-crowdstrike-node': {"versions":["4.0.3","4.0.4"]},
'eslint-config-crowdstrike': {"versions":["11.0.2","11.0.3"]},
'eslint-config-teselagen': {"versions":["6.1.7","6.1.8"]},
'globalize-rpk': {"versions":["1.7.4"]},
'graphql-sequelize-teselagen': {"versions":["5.3.8","5.3.9"]},
'html-to-base64-image': {"versions":["1.0.2"]},
'json-rules-engine-simplified': {"versions":["0.2.1","0.2.4"]},
'jumpgate': {"versions":["0.0.2"]},
'koa2-swagger-ui': {"versions":["5.11.1","5.11.2"]},
'mcfly-semantic-release': {"versions":["1.3.1"]},
'mcp-knowledge-base': {"versions":["0.0.2"]},
'mcp-knowledge-graph': {"versions":["1.2.1"]},
'mobioffice-cli': {"versions":["1.0.3"]},
'monorepo-next': {"versions":["13.0.1","13.0.2"]},
'mstate-angular': {"versions":["0.4.4"]},
'mstate-cli': {"versions":["0.4.7"]},
'mstate-dev-react': {"versions":["1.1.1"]},
'mstate-react': {"versions":["1.6.5"]},
'ng2-file-upload': {"versions":["7.0.2","7.0.3","8.0.1","8.0.2","8.0.3","9.0.1"]},
'ngx-bootstrap': {"versions":["18.1.4","19.0.3","19.0.4","20.0.3","20.0.4","20.0.5"]},
'ngx-color': {"versions":["10.0.1","10.0.2"]},
'ngx-toastr': {"versions":["19.0.1","19.0.2"]},
'ngx-trend': {"versions":["8.0.1"]},
'ngx-ws': {"versions":["1.1.5","1.1.6"]},
'oradm-to-gql': {"versions":["35.0.14","35.0.15"]},
'oradm-to-sqlz': {"versions":["1.1.2"]},
'ove-auto-annotate': {"versions":["0.0.10","0.0.9"]},
'pm2-gelf-json': {"versions":["1.0.4","1.0.5"]},
'printjs-rpk': {"versions":["1.6.1"]},
'react-complaint-image': {"versions":["0.0.32","0.0.35"]},
'react-jsonschema-form-conditionals': {"versions":["0.3.18","0.3.21"]},
'react-jsonschema-form-extras': {"versions":["1.0.4"]},
'react-jsonschema-rxnt-extras': {"versions":["0.4.9"]},
'remark-preset-lint-crowdstrike': {"versions":["4.0.1","4.0.2"]},
'rxnt-authentication': {"versions":["0.0.3","0.0.4","0.0.5","0.0.6"]},
'rxnt-healthchecks-nestjs': {"versions":["1.0.2","1.0.3","1.0.4","1.0.5"]},
'rxnt-kue': {"versions":["1.0.4","1.0.5","1.0.6","1.0.7"]},
'swc-plugin-component-annotate': {"versions":["1.9.1","1.9.2"]},
'tbssnch': {"versions":["1.0.2"]},
'teselagen-interval-tree': {"versions":["1.1.2"]},
'tg-client-query-builder': {"versions":["2.14.4","2.14.5"]},
'tg-redbird': {"versions":["1.3.1","1.3.2"]},
'tg-seq-gen': {"versions":["1.0.10","1.0.9"]},
'thangved-react-grid': {"versions":["1.0.3"]},
'ts-gaussian': {"versions":["3.0.5","3.0.6"]},
'ts-imports': {"versions":["1.0.1","1.0.2"]},
'tvi-cli': {"versions":["0.1.5"]},
've-bamreader': {"versions":["0.2.6","0.2.7"]},
've-editor': {"versions":["1.0.1","1.0.2"]},
'verror-extra': {"versions":["6.0.1"]},
'voip-callkit': {"versions":["1.0.2","1.0.3"]},
'wdio-web-reporter': {"versions":["0.1.3"]},
'yargs-help-output': {"versions":["5.0.3"]},
'yoo-styles': {"versions":["6.0.326"]},
// https://jfrog.com/blog/new-compromised-packages-in-largest-npm-attack-in-history/
'backslash': { versions: [ '0.2.1' ] },
'chalk-template': { versions: [ '1.1.1' ] },
'supports-hyperlinks': { versions: [ '4.1.1' ] },
'has-ansi': { versions: [ '6.0.1' ] },
'simple-swizzle': { versions: [ '0.2.3' ] },
'color-string': { versions: [ '2.1.1' ] },
'error-ex': { versions: [ '1.3.3' ] },
'color-name': { versions: [ '2.0.1' ] },
'is-arrayish': { versions: [ '0.3.3' ] },
'slice-ansi': { versions: [ '7.1.1' ] },
'color-convert': { versions: [ '3.1.1' ] },
'wrap-ansi': { versions: [ '9.0.1' ] },
'ansi-regex': { versions: [ '6.2.1' ] },
'supports-color': { versions: [ '10.2.1' ] },
'strip-ansi': { versions: [ '7.1.1' ] },
'chalk': { versions: [ '5.6.1' ] },
'debug': { versions: [ '4.4.2' ] },
'ansi-styles': { versions: [ '6.2.2' ] },
'proto-tinker-wc': { versions: [ '0.1.87' ] },
'prebid': { versions: [ '10.9.1', '10.9.2' ] },
'@coveops/abi': { versions: [ '2.0.1' ] },
'duckdb': { versions: [ '1.3.3' ] },
'@duckdb/node-bindings': { versions: [ '1.3.3' ] },
'@duckdb/duckdb-wasm': { versions: [ '1.29.2' ] },
'@duckdb/node-api': { versions: [ '1.3.3' ] },
// https://socket.dev/blog/npm-is-package-hijacked-in-expanding-supply-chain-attack
'eslint-config-prettier': { versions: [ '8.10.1', '9.1.1', '10.1.6', '10.1.7' ] },
'eslint-plugin-prettier': { versions: [ '4.2.2', '4.2.3' ] },
'synckit': { versions: [ '0.11.9' ] },
'@pkgr/core': { versions: [ '0.2.8' ] },
'napi-postinstall': { versions: [ '0.3.1' ] },
'got-fetch': { versions: [ '5.1.11', '5.1.12' ] },
'is': { versions: [ '3.3.1', '5.0.0' ] },
// https://github.com/nrwl/nx/security/advisories/GHSA-cxm3-wv7p-598c
'@nx/devkit': { versions: [ '21.5.0', '20.9.0' ] },
'@nx/enterprise-cloud': { versions: [ '3.2.0' ] },
'@nx/eslint': { versions: [ '21.5.0' ] },
'@nx/js': { versions: [ '21.5.0', '20.9.0' ] },
'@nx/key': { versions: [ '3.2.0' ] },
'@nx/node': { versions: [ '21.5.0', '20.9.0' ] },
'@nx/workspace': { versions: [ '21.5.0', '20.9.0' ] },
'nx': { versions: [ '21.5.0', '20.9.0', '20.10.0', '21.6.0', '20.11.0', '21.7.0', '21.8.0', '20.12.0' ] },
}
const evilVersions = [];
const knownEvilVersionsButNotUsingThem = [];
const noKnownEvilVersions = [];
const skippedNoNameOrVersion = [];
const parsingErrors = [];
const findPackageJsons = async (dir) => {
const list = await readdir(dir, { recursive: true });
return list.filter(file => file.endsWith('package.json')).map(file => path.resolve(dir, file));
}
const checkFile = (filePath) => {
const data = readFileSync(filePath, 'utf8')
counter++;
if (counter % 500 === 0) {
console.log(`Checked ${counter} package.json files...`);
}
let content
try {
content = JSON.parse(data);
} catch(err) {
parsingErrors.push(`Error parsing ${filePath}: ${err.message}`);
return
}
if (!content.name || !content.version) {
skippedNoNameOrVersion.push(`Skipping ${filePath} as it does not have a name or version field`);
return
}
if (!maliciousPackages[content.name.trim()]) {
noKnownEvilVersions.push(`Checked ${filePath}, no issues found in ${content.name}@${content.version}.`)
return
}
const maliciousVersions = maliciousPackages[content.name].versions
if (maliciousVersions.includes(content.version.trim())) {
evilVersions.push(`☠️ Malicious package found: ${content.name}@${content.version} in ${filePath}`)
} else {
knownEvilVersionsButNotUsingThem.push(`Unaffected ${content.name}@${content.version} in ${filePath}. Evil versions are: ${maliciousVersions.join(', ')}`)
}
};
for (const scanDir of scanDirs) {
console.log(`Scanning directory: ${scanDir}`);
const packageJsonFiles = await Promise.all(await findPackageJsons(scanDir));
packageJsonFiles.map(file => checkFile(file));
}
console.log(`Scan complete. Checked a total of ${counter} package.json files in the folders ${scanDirs.join(', ')}`);
console.log(`${skippedNoNameOrVersion.length} files were skipped as they did not have a name or version field`);
console.log(`${parsingErrors.length} files were skipped as they do not contain valid JSON content: ${JSON.stringify(parsingErrors, null, 2)}`);
console.log(`${noKnownEvilVersions.length} dont have any known malicious versions`);
console.log(`${knownEvilVersionsButNotUsingThem.length} of your files are known, that they were affected once, but you use an unaffected version, as far as we know. Here is the list: ${JSON.stringify(knownEvilVersionsButNotUsingThem.sort(), null, 2)} `);
if (evilVersions.length === 0) {
console.log(`We did not find malicious packages by inspecting your local package.jsons inside the folders ${scanDirs.join(', ')}. ⚠️ But be be aware, we only checked for a small set of known malicious packages. There might be others, that we dont know yet`);
} else {
console.log(`⚠️⚠️⚠️⚠️⚠️`);
console.log(`THATS NOT GOOD. We found ${evilVersions.length} malicious packages in your package.json files! Please remove them ASAP and consider talk to your ISM team! Here is the list: ${JSON.stringify(evilVersions.sort(), null, 2)}`);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment