Skip to content

Instantly share code, notes, and snippets.

@bbsmithy
Last active November 25, 2025 16:32
Show Gist options
  • Select an option

  • Save bbsmithy/df56a0dc6b366fdb44e525f2d60ed505 to your computer and use it in GitHub Desktop.

Select an option

Save bbsmithy/df56a0dc6b366fdb44e525f2d60ed505 to your computer and use it in GitHub Desktop.
Check your js project for compromised Sha1-Hulud packages
#!/usr/bin/env node
const COMPROMISED_PACKAGES = [
"@asyncapi/diff",
"@asyncapi/nodejs-ws-template",
"go-template",
"@asyncapi/avro-schema-parser",
"@asyncapi/converter",
"@asyncapi/dotnet-rabbitmq-template",
"@asyncapi/nunjucks-filters",
"@asyncapi/protobuf-schema-parser",
"@asyncapi/problem",
"@asyncapi/optimizer",
"@asyncapi/python-paho-template",
"@asyncapi/multi-parser",
"@asyncapi/bundler",
"@asyncapi/php-template",
"asyncapi-preview",
"@asyncapi/java-spring-cloud-stream-template",
"@asyncapi/modelina-cli",
"@asyncapi/generator-helpers",
"@asyncapi/java-template",
"@asyncapi/react-component",
"@asyncapi/generator",
"@asyncapi/server-api",
"@asyncapi/java-spring-template",
"@asyncapi/cli",
"@asyncapi/web-component",
"@asyncapi/specs",
"@asyncapi/modelina",
"@asyncapi/parser",
"@asyncapi/html-template",
"@asyncapi/go-watermill-template",
"@asyncapi/openapi-schema-parser",
"@asyncapi/edavisualiser",
"@asyncapi/generator-components",
"dotnet-template",
"@asyncapi/keeper",
"github-action-for-generator",
"@asyncapi/nodejs-template",
"@asyncapi/markdown-template",
"@quick-start-soft/quick-git-clean-markdown",
"@quick-start-soft/quick-markdown-image",
"@quick-start-soft/quick-markdown-translator",
"@quick-start-soft/quick-markdown",
"test23112222-api",
"@asyncapi/generator-react-sdk",
"@quick-start-soft/quick-markdown-compose",
"iron-shield-miniapp",
"manual-billing-system-miniapp-api",
"shinhan-limit-scrap",
"@strapbuild/react-native-perspective-image-cropper",
"react-native-use-modal",
"@quick-start-soft/quick-task-refine",
"@strapbuild/react-native-date-time-picker",
"@strapbuild/react-native-perspective-image-cropper-2",
"create-glee-app",
"@strapbuild/react-native-perspective-image-cropper-poojan31",
"@asyncapi/studio",
"@quick-start-soft/quick-markdown-print",
"@quick-start-soft/quick-remove-image-background",
"eslint-config-zeallat-base",
"korea-administrative-area-geo-json-util",
"@quick-start-soft/quick-document-translator",
"axios-builder",
"posthog-node",
"@posthog/first-time-event-tracker",
"@posthog/event-sequence-timer-plugin",
"@posthog/gitub-star-sync-plugin",
"posthog-plugin-hello-world",
"@posthog/bitbucket-release-tracker",
"@posthog/maxmind-plugin",
"@posthog/postgres-plugin",
"@posthog/twilio-plugin",
"@posthog/cli",
"@posthog/clickhouse",
"@posthog/snowflake-export-plugin",
"posthog-react-native-session-replay",
"@posthog/drop-events-on-property-plugin",
"@posthog/github-release-tracking-plugin",
"@posthog/icons",
"@posthog/geoip-plugin",
"@posthog/intercom-plugin",
"@posthog/plugin-unduplicates",
"@posthog/react-rrweb-player",
"drop-events-on-property-plugin",
"@posthog/ingestion-alert-plugin",
"@posthog/kinesis-plugin",
"@posthog/laudspeaker-plugin",
"@posthog/nextjs",
"@posthog/nextjs-config",
"@posthog/automatic-cohorts-plugin",
"@posthog/migrator3000-plugin",
"@posthog/pagerduty-plugin",
"@posthog/plugin-contrib",
"@posthog/sendgrid-plugin",
"@posthog/customerio-plugin",
"@posthog/rrweb-utils",
"@posthog/taxonomy-plugin",
"@posthog/zendesk-plugin",
"@posthog/netdata-event-processing",
"@posthog/url-normalizer-plugin",
"posthog-docusaurus",
"@posthog/currency-normalization-plugin",
"@posthog/filter-out-plugin",
"@posthog/heartbeat-plugin",
"@actbase/react-native-fast-image",
"@posthog/ai",
"@posthog/databricks-plugin",
"@actbase/react-native-kakao-channel",
"calc-loan-interest",
"@actbase/react-absolute",
"@actbase/react-daum-postcode",
"@actbase/react-native-simple-video",
"@posthog/core",
"@posthog/lemon-ui",
"@seung-ju/next",
"@seung-ju/react-hooks",
"posthog-react-native",
"@actbase/css-to-react-native-transform",
"@actbase/react-native-actionsheet",
"@actbase/react-native-tiktok",
"@seung-ju/react-native-action-sheet",
"@actbase/react-kakaosdk",
"@posthog/agent",
"@posthog/variance-plugin",
"discord-bot-server",
"@posthog/rrweb-replay",
"@posthog/rrweb-snapshot",
"@actbase/node-server",
"@actbase/react-native-devtools",
"@posthog/plugin-server",
"@posthog/rrweb-record",
"@actbase/native",
"@actbase/react-native-less-transformer",
"@posthog/rrweb",
"posthog-js",
"@posthog/web-dev-server",
"@posthog/piscina",
"@posthog/nuxt",
"@posthog/rrweb-player",
"@posthog/wizard",
"@actbase/react-native-kakao-navi",
"@posthog/siphash",
"@posthog/twitter-followers-plugin",
"@actbase/react-native-naver-login",
"@seung-ju/openapi-generator",
"@posthog/rrdom",
"@posthog/hedgehog-mode",
"react-native-worklet-functions",
"expo-audio-session",
"poper-react-sdk",
"@postman/secret-scanner-wasm",
"@postman/csv-parse",
"@postman/node-keytar",
"@postman/tunnel-agent",
"@postman/pm-bin-macos-arm64",
"@postman/pm-bin-linux-x64",
"@postman/postman-collection-fork",
"@postman/postman-mcp-server",
"@postman/wdio-junit-reporter",
"@postman/aether-icons",
"@postman/postman-mcp-cli",
"@postman/pretty-ms",
"@postman/pm-bin-windows-x64",
"@postman/wdio-allure-reporter",
"@postman/final-node-keytar",
"@postman/pm-bin-macos-x64",
"@aryanhussain/my-angular-lib",
"capacitor-plugin-apptrackingios",
"capacitor-plugin-purchase",
"capacitor-purchase-history",
"capacitor-voice-recorder-wav",
"scgs-capacitor-subscribe",
"@postman/mcp-ui-client",
"capacitor-plugin-scgssigninwithgoogle",
"@kvytech/medusa-plugin-announcement",
"@kvytech/medusa-plugin-product-reviews",
"medusa-plugin-zalopay",
"scgsffcreator",
"@kvytech/habbit-e2e-test",
"medusa-plugin-logs",
"medusa-plugin-product-reviews-kvy",
"@kvytech/medusa-plugin-promotion",
"medusa-plugin-momo",
"@kvytech/components",
"medusa-plugin-announcement",
"@kvytech/cli",
"@kvytech/medusa-plugin-newsletter",
"@kvytech/medusa-plugin-management",
"@kvytech/web",
"create-hardhat3-app",
"test-hardhat-app",
"evm-checkcode-cli",
"gate-evm-tools-test",
"gate-evm-check-code2",
"web-types-htmx",
"test-foundry-app",
"web-types-lit",
"bun-plugin-httpfile",
"open2internet",
"vite-plugin-httpfile",
"@ensdomains/vite-plugin-i18next-loader",
"@ensdomains/blacklist",
"@ensdomains/durin",
"@ensdomains/renewal",
"@ensdomains/cypress-metamask",
"bytecode-checker-cli",
"@ensdomains/dnsprovejs",
"@ensdomains/ccip-read-dns-gateway",
"@ensdomains/ccip-read-cf-worker",
"@ensdomains/dnssec-oracle-anchors",
"@ensdomains/reverse-records",
"@ensdomains/ens-test-env",
"@ensdomains/hackathon-registrar",
"@ensdomains/renewal-widget",
"crypto-addr-codec",
"@ensdomains/solsha1",
"@ensdomains/server-analytics",
"@ensdomains/ui",
"@ensdomains/test-utils",
"@ensdomains/mock",
"@ensdomains/ccip-read-router",
"@zapier/babel-preset-zapier",
"@ensdomains/hardhat-chai-matchers-viem",
"@ensdomains/ccip-read-worker-viem",
"@zapier/browserslist-config-zapier",
"@zapier/zapier-sdk",
"@zapier/stubtree",
"zapier-async-storage",
"@zapier/ai-actions",
"@zapier/mcp-integration",
"@zapier/spectral-api-ruleset",
"@ensdomains/address-encoder",
"redux-router-kit",
"@ensdomains/eth-ens-namehash",
"zapier-scripts",
"@ensdomains/buffer",
"@ensdomains/thorin",
"zapier-platform-legacy-scripting-runner",
"zapier-platform-schema",
"@ensdomains/dnssecoraclejs",
"zapier-platform-core",
"@ensdomains/op-resolver-contracts",
"@ensdomains/ens-archived-contracts",
"@ensdomains/ensjs",
"@ensdomains/subdomain-registrar",
"@ensdomains/unruggable-gateways",
"@ensdomains/web3modal",
"zapier-platform-cli",
"@ensdomains/ens-contracts",
"@ensdomains/react-ens-address",
"@ensdomains/curvearithmetics",
"@zapier/secret-scrubber",
"@ensdomains/hardhat-toolbox-viem-extended",
"ethereum-ens",
"@ensdomains/durin-middleware",
"@ensdomains/unicode-confusables",
"@ensdomains/ensjs-react",
"@ensdomains/content-hash",
"@ensdomains/ens-avatar",
"@zapier/ai-actions-react",
"@zapier/eslint-plugin-zapier",
"@ensdomains/offchain-resolver-contracts",
"@ensdomains/ens-validation",
"@ensdomains/name-wrapper",
"@hapheus/n8n-nodes-pgp",
"@markvivanco/app-version-checker",
"claude-token-updater",
"n8n-nodes-tmdb",
"devstart-cli",
"skills-use",
"@mcp-use/inspector",
"zuper-sdk",
"zuper-stream",
"@mcp-use/mcp-use",
"create-mcp-use-app",
"mcp-use",
"@mcp-use/cli",
"zuper-cli",
"@caretive/caret-cli",
"cpu-instructions",
"lite-serper-mcp-server",
"@louisle2/core",
"jan-browser",
"exact-ticker",
"react-library-setup",
"orbit-soap",
"@orbitgtbelgium/mapbox-gl-draw-scale-rotate-mode",
"token.js-fork",
"react-component-taggers",
"@louisle2/cortex-js",
"orbit-nebula-editor",
"@trigo/pathfinder-ui-css",
"@trigo/jsdt",
"@trigo/atrix-redis",
"@trigo/eslint-config-trigo",
"@trigo/atrix-orientdb",
"@trigo/node-soap",
"eslint-config-trigo",
"@trigo/bool-expressions",
"@trigo/atrix-pubsub",
"@trigo/atrix-elasticsearch",
"@trigo/hapi-auth-signedlink",
"@trigo/keycloak-api",
"@trigo/atrix-soap",
"@trigo/atrix-swagger",
"@trigo/atrix-acl",
"atrix",
"redux-forge",
"@trigo/atrix-mongoose",
"@trigo/atrix",
"orbit-boxicons",
"atrix-mongoose",
"bool-expressions",
"react-element-prompt-inspector",
"trigo-react-app",
"@trigo/trigo-hapijs",
"@trigo/fsm",
"command-irail",
"@orbitgtbelgium/mapbox-gl-draw-cut-polygon-mode",
"@trigo/atrix-postgres",
"@orbitgtbelgium/time-slider",
"@orbitgtbelgium/orbit-components",
"orbit-nebula-draw-tools",
"typeorm-orbit",
"@mparpaillon/connector-parse",
"@mparpaillon/imagesloaded",
"@commute/market-data",
"gitsafe",
"@osmanekrem/error-handler",
"@commute/bloom",
"okta-react-router-6",
"designstudiouiux",
"itobuz-angular",
"@ifelsedeveloper/protocol-contracts-svm-idl",
"ito-button",
"@dev-blinq/cucumber_client",
"blinqio-executions-cli",
"itobuz-angular-auth",
"@dev-blinq/ai-qa-logic",
"axios-timed",
"react-native-email",
"tenacious-fetch",
"kill-port",
"jacob-zuma",
"luno-api",
"@lessondesk/eslint-config",
"sort-by-distance",
"just-toasty",
"image-to-uri",
"react-native-phone-call",
"formik-error-focus",
"jquery-bindings",
"@lessondesk/babel-preset",
"barebones-css",
"coinmarketcap-api",
"license-o-matic",
"@varsityvibe/api-client",
"pico-uid",
"hyperterm-hipster",
"set-nested-prop",
"bytes-to-x",
"enforce-branch-name",
"fittxt",
"get-them-args",
"react-native-retriable-fetch",
"svelte-autocomplete-select",
"feature-flip",
"lint-staged-imagemin",
"react-native-view-finder",
"formik-store",
"shell-exec",
"react-native-log-level",
"@everreal/web-analytics",
"react-native-jam-icons",
"@thedelta/eslint-config",
"parcel-plugin-asset-copier",
"react-native-websocket",
"ra-data-firebase",
"react-jam-icons",
"react-native-fetch",
"@ifings/design-system",
"gatsby-plugin-cname",
"@alexcolls/nuxt-ux",
"react-native-datepicker-modal",
"undefsafe-typed",
"chrome-extension-downloads",
"@alexcolls/nuxt-socket.io",
"fuzzy-finder",
"sa-company-registration-number-regex",
"flapstacks",
"react-keycloak-context",
"react-qr-image",
"@tiaanduplessis/react-progressbar",
"@lessondesk/schoolbus",
"@tiaanduplessis/json",
"react-native-get-pixel-dimensions",
"nanoreset",
"next-circular-dependency",
"url-encode-decode",
"axios-cancelable",
"compare-obj",
"wenk",
"haufe-axera-api-client",
"obj-to-css",
"sa-id-gen",
"@lessondesk/api-client",
"@varsityvibe/validation-schemas",
"flatten-unflatten",
"stoor",
"@clausehq/flows-step-jsontoxml",
"@accordproject/concerto-analysis",
"hope-mapboxdraw",
"count-it-down",
"hopedraw",
"@accordproject/markdown-it-cicero",
"piclite",
"@fishingbooker/react-swiper",
"@fishingbooker/browser-sync-plugin",
"generator-meteor-stock",
"@fishingbooker/react-loader",
"benmostyn-frame-print",
"@fishingbooker/react-pagination",
"@voiceflow/anthropic",
"@voiceflow/voice-types",
"@voiceflow/default-prompt-wrappers",
"@voiceflow/npm-package-json-lint-config",
"@voiceflow/nestjs-mongodb",
"@voiceflow/tsconfig",
"@voiceflow/test-common",
"@voiceflow/husky-config",
"@voiceflow/commitlint-config",
"@voiceflow/git-branch-check",
"normal-store",
"@voiceflow/prettier-config",
"@voiceflow/stylelint-config",
"vf-oss-template",
"@voiceflow/storybook-config",
"@voiceflow/verror",
"@voiceflow/alexa-types",
"@voiceflow/nestjs-timeout",
"@voiceflow/serverless-plugin-typescript",
"@voiceflow/voiceflow-types",
"shelf-jwt-sessions",
"@hover-design/react",
"@voiceflow/base-types",
"@voiceflow/eslint-config",
"@voiceflow/fetch",
"@voiceflow/common",
"@voiceflow/eslint-plugin",
"@voiceflow/exception",
"@voiceflow/dtos-interact",
"@voiceflow/google-types",
"@voiceflow/nestjs-common",
"@voiceflow/pino",
"@voiceflow/sdk-runtime",
"@voiceflow/nestjs-rate-limit",
"@voiceflow/openai",
"dialogflow-es",
"@voiceflow/widget",
"arc-cli-fc",
"composite-reducer",
"bidirectional-adapter",
"@antstackio/express-graphql-proxy",
"@antstackio/json-to-graphql",
"@voiceflow/body-parser",
"@voiceflow/logger",
"@antstackio/eslint-config-antstack",
"@voiceflow/vitest-config",
"@faq-component/core",
"@pruthvi21/use-debounce",
"@voiceflow/api-sdk",
"@hover-design/core",
"@faq-component/react",
"@voiceflow/semantic-release-config",
"@voiceflow/vite-config",
"@voiceflow/circleci-config-sdk-orb-import",
"@voiceflow/backend-utils",
"@voiceflow/slate-serializer",
"@voiceflow/google-dfes-types",
"n8n-nodes-viral-app",
"@accordproject/markdown-docx",
"@clausehq/flows-step-sendgridemail",
"@lpdjs/firestore-repo-service",
"@trefox/sleekshop-js",
"invo",
"jsonsurge",
"mon-package-react-typescript",
"rediff",
"solomon-api-stories",
"solomon-v3-stories",
"solomon-v3-ui-wrapper",
"tcsp-draw-test",
"uplandui"
];
const path = require('path')
const fs = require('fs');
/**
* Finds package.json in the given directory or parent directories
* @param {string} startDir - Directory to start searching from
* @returns {string|null} Path to package.json or null if not found
*/
function findPackageJson(startDir) {
let currentDir = path.resolve(startDir);
const root = path.parse(currentDir).root;
while (currentDir !== root) {
const packageJsonPath = path.join(currentDir, 'package.json');
if (fs.existsSync(packageJsonPath)) {
return packageJsonPath;
}
currentDir = path.dirname(currentDir);
}
return null;
}
/**
* Reads and parses package.json
* @param {string} packageJsonPath - Path to package.json
* @returns {object|null} Parsed package.json or null if error
*/
function readPackageJson(packageJsonPath) {
try {
const content = fs.readFileSync(packageJsonPath, 'utf8');
return JSON.parse(content);
} catch (error) {
console.error(`Error reading package.json: ${error.message}`);
return null;
}
}
/**
* Collects all dependencies from package.json
* @param {object} packageJson - Parsed package.json object
* @returns {Set<string>} Set of all dependency names
*/
function getAllDependencies(packageJson) {
const deps = new Set();
// Check all dependency sections
const sections = [
'dependencies',
'devDependencies',
'peerDependencies',
'optionalDependencies'
];
sections.forEach(section => {
if (packageJson[section] && typeof packageJson[section] === 'object') {
Object.keys(packageJson[section]).forEach(pkg => deps.add(pkg));
}
});
return deps;
}
/**
* Main function
*/
function main() {
// Get command line arguments
const args = process.argv.slice(2);
// Determine search directory (default to current working directory)
const searchDir = args[0] || process.cwd();
console.log(`Using COMPROMISED_PACKAGES array (${COMPROMISED_PACKAGES.length} packages)`);
console.log(`Searching for package.json in: ${searchDir}\n`);
// Use the COMPROMISED_PACKAGES array
const effectedPackages = COMPROMISED_PACKAGES;
// Find package.json
const packageJsonPath = findPackageJson(searchDir);
if (!packageJsonPath) {
console.error('Error: package.json not found in directory or parent directories');
process.exit(1);
}
console.log(`Found package.json at: ${packageJsonPath}\n`);
// Read package.json
const packageJson = readPackageJson(packageJsonPath);
if (!packageJson) {
process.exit(1);
}
// Get all dependencies
const allDependencies = getAllDependencies(packageJson);
// Find matches
const matches = [];
const foundInSection = {
dependencies: [],
devDependencies: [],
peerDependencies: [],
optionalDependencies: []
};
effectedPackages.forEach(pkg => {
if (allDependencies.has(pkg)) {
matches.push(pkg);
// Determine which section(s) it's in
if (packageJson.dependencies && packageJson.dependencies[pkg]) {
foundInSection.dependencies.push(pkg);
}
if (packageJson.devDependencies && packageJson.devDependencies[pkg]) {
foundInSection.devDependencies.push(pkg);
}
if (packageJson.peerDependencies && packageJson.peerDependencies[pkg]) {
foundInSection.peerDependencies.push(pkg);
}
if (packageJson.optionalDependencies && packageJson.optionalDependencies[pkg]) {
foundInSection.optionalDependencies.push(pkg);
}
}
});
// Print results
console.log('='.repeat(60));
console.log('RESULTS');
console.log('='.repeat(60));
console.log(`Total packages checked: ${effectedPackages.length}`);
console.log(`Matches found: ${matches.length}\n`);
if (matches.length > 0) {
console.log('Found packages:');
console.log('-'.repeat(60));
matches.forEach(pkg => {
const sections = [];
if (foundInSection.dependencies.includes(pkg)) sections.push('dependencies');
if (foundInSection.devDependencies.includes(pkg)) sections.push('devDependencies');
if (foundInSection.peerDependencies.includes(pkg)) sections.push('peerDependencies');
if (foundInSection.optionalDependencies.includes(pkg)) sections.push('optionalDependencies');
const version = packageJson.dependencies?.[pkg] ||
packageJson.devDependencies?.[pkg] ||
packageJson.peerDependencies?.[pkg] ||
packageJson.optionalDependencies?.[pkg] || '';
console.log(` ✓ ${pkg} (${sections.join(', ')}) ${version}`);
});
console.log('\n' + '-'.repeat(60));
} else {
console.log('No matching packages found in package.json');
}
// Exit with appropriate code
process.exit(matches.length > 0 ? 0 : 0);
}
// Run the script
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment