Skip to content

Instantly share code, notes, and snippets.

@koji
Last active November 30, 2025 01:07
Show Gist options
  • Select an option

  • Save koji/703053a4edc9d457d9fc26a11079d79e to your computer and use it in GitHub Desktop.

Select an option

Save koji/703053a4edc9d457d9fc26a11079d79e to your computer and use it in GitHub Desktop.
check packages that are compromised by Shai-Hulud

compromised packages list
https://www.mend.io/blog/npm-supply-chain-attack-packages-compromised-by-self-spreading-malware/

the latest list
https://github.com/wiz-sec-public/wiz-research-iocs/blob/main/reports/shai-hulud-2-packages.csv

support yarn v1, npm, and pnpm

#!/usr/bin/env node

const fs = require('fs');
const path = require('path');

// ==========================================
// 1. Configuration and Data Definitions
// ==========================================

// Shai-Hulud compromised package list
const shaiHuludCompromisedPackages = [
  { package: "02-echo", versions: ["0.0.7"] },
  { package: "@accordproject/concerto-analysis", versions: ["3.24.1"] },
  { package: "@accordproject/concerto-linter", versions: ["3.24.1"] },
  { package: "@accordproject/concerto-linter-default-ruleset", versions: ["3.24.1"] },
  { package: "@accordproject/concerto-metamodel", versions: ["3.12.5"] },
  { package: "@accordproject/concerto-types", versions: ["3.24.1"] },
  { package: "@accordproject/markdown-it-cicero", versions: ["0.16.26"] },
  { package: "@accordproject/template-engine", versions: ["2.7.2"] },
  { package: "@actbase/css-to-react-native-transform", versions: ["1.0.3"] },
  { package: "@actbase/native", versions: ["0.1.32"] },
  { package: "@actbase/node-server", versions: ["1.1.19"] },
  { package: "@actbase/react-absolute", versions: ["0.8.3"] },
  { package: "@actbase/react-daum-postcode", versions: ["1.0.5"] },
  { package: "@actbase/react-kakaosdk", versions: ["0.9.27"] },
  { package: "@actbase/react-native-actionsheet", versions: ["1.0.3"] },
  { package: "@actbase/react-native-devtools", versions: ["0.1.3"] },
  { package: "@actbase/react-native-fast-image", versions: ["8.5.13"] },
  { package: "@actbase/react-native-kakao-channel", versions: ["1.0.2"] },
  { package: "@actbase/react-native-kakao-navi", versions: ["2.0.4"] },
  { package: "@actbase/react-native-less-transformer", versions: ["1.0.6"] },
  { package: "@actbase/react-native-naver-login", versions: ["1.0.1"] },
  { package: "@actbase/react-native-simple-video", versions: ["1.0.13"] },
  { package: "@actbase/react-native-tiktok", versions: ["1.1.3"] },
  { package: "@afetcan/api", versions: ["0.0.13"] },
  { package: "@afetcan/storage", versions: ["0.0.27"] },
  { package: "@alaan/s2s-auth", versions: ["2.0.3"] },
  { package: "@alexadark/amadeus-api", versions: ["1.0.4"] },
  { package: "@alexadark/gatsby-theme-events", versions: ["1.0.1"] },
  { package: "@alexadark/gatsby-theme-wordpress-blog", versions: ["2.0.1"] },
  { package: "@alexadark/reusable-functions", versions: ["1.5.1"] },
  { package: "@alexcolls/nuxt-socket.io", versions: ["0.0.7", "0.0.8"] },
  { package: "@alexcolls/nuxt-ux", versions: ["0.6.1", "0.6.2"] },
  { package: "@antstackio/eslint-config-antstack", versions: ["0.0.3"] },
  { package: "@antstackio/express-graphql-proxy", versions: ["0.2.8"] },
  { package: "@antstackio/graphql-body-parser", versions: ["0.1.1"] },
  { package: "@antstackio/json-to-graphql", versions: ["1.0.3"] },
  { package: "@antstackio/shelbysam", versions: ["1.1.7"] },
  { package: "@aryanhussain/my-angular-lib", versions: ["0.0.23"] },
  { package: "@asyncapi/avro-schema-parser", versions: ["3.0.25", "3.0.26"] },
  { package: "@asyncapi/bundler", versions: ["0.6.5", "0.6.6"] },
  { package: "@asyncapi/cli", versions: ["4.1.3", "4.1.2"] },
  { package: "@asyncapi/converter", versions: ["1.6.3", "1.6.4"] },
  { package: "@asyncapi/diff", versions: ["0.5.1", "0.5.2"] },
  { package: "@asyncapi/dotnet-rabbitmq-template", versions: ["1.0.2", "1.0.1"] },
  { package: "@asyncapi/edavisualiser", versions: ["1.2.2", "1.2.1"] },
  { package: "@asyncapi/generator", versions: ["2.8.5", "2.8.6"] },
  { package: "@asyncapi/generator-components", versions: ["0.3.2", "0.3.3"] },
  { package: "@asyncapi/generator-helpers", versions: ["0.2.1", "0.2.2"] },
  { package: "@asyncapi/generator-react-sdk", versions: ["1.1.5", "1.1.4"] },
  { package: "@asyncapi/go-watermill-template", versions: ["0.2.77", "0.2.76"] },
  { package: "@asyncapi/html-template", versions: ["3.3.2", "3.3.3"] },
  { package: "@asyncapi/java-spring-cloud-stream-template", versions: ["0.13.5", "0.13.6"] },
  { package: "@asyncapi/java-spring-template", versions: ["1.6.2", "1.6.1"] },
  { package: "@asyncapi/java-template", versions: ["0.3.6", "0.3.5"] },
  { package: "@asyncapi/keeper", versions: ["0.0.2", "0.0.3"] },
  { package: "@asyncapi/markdown-template", versions: ["1.6.8", "1.6.9"] },
  { package: "@asyncapi/modelina", versions: ["5.10.3", "5.10.2"] },
  { package: "@asyncapi/modelina-cli", versions: ["5.10.3", "5.10.2"] },
  { package: "@asyncapi/multi-parser", versions: ["2.2.1", "2.2.2"] },
  { package: "@asyncapi/nodejs-template", versions: ["3.0.6", "3.0.5"] },
  { package: "@asyncapi/nodejs-ws-template", versions: ["0.10.1", "0.10.2"] },
  { package: "@asyncapi/nunjucks-filters", versions: ["2.1.1", "2.1.2"] },
  { package: "@asyncapi/openapi-schema-parser", versions: ["3.0.25", "3.0.26"] },
  { package: "@asyncapi/optimizer", versions: ["1.0.6", "1.0.5"] },
  { package: "@asyncapi/parser", versions: ["3.4.1", "3.4.2"] },
  { package: "@asyncapi/php-template", versions: ["0.1.1", "0.1.2"] },
  { package: "@asyncapi/problem", versions: ["1.0.2", "1.0.1"] },
  { package: "@asyncapi/protobuf-schema-parser", versions: ["3.5.2", "3.6.1", "3.5.3"] },
  { package: "@asyncapi/python-paho-template", versions: ["0.2.15", "0.2.14"] },
  { package: "@asyncapi/react-component", versions: ["2.6.7", "2.6.6"] },
  { package: "@asyncapi/server-api", versions: ["0.16.24", "0.16.25"] },
  { package: "@asyncapi/specs", versions: ["6.9.1", "6.10.1", "6.8.3", "6.8.2"] },
  { package: "@asyncapi/studio", versions: ["1.0.3", "1.0.2"] },
  { package: "@asyncapi/web-component", versions: ["2.6.7", "2.6.6"] },
  { package: "@bdkinc/knex-ibmi", versions: ["0.5.7"] },
  { package: "@browserbasehq/bb9", versions: ["1.2.21"] },
  { package: "@browserbasehq/director-ai", versions: ["1.0.3"] },
  { package: "@browserbasehq/mcp", versions: ["2.1.1"] },
  { package: "@browserbasehq/mcp-server-browserbase", versions: ["2.4.2"] },
  { package: "@browserbasehq/sdk-functions", versions: ["0.0.4"] },
  { package: "@browserbasehq/stagehand", versions: ["3.0.4"] },
  { package: "@browserbasehq/stagehand-docs", versions: ["1.0.1"] },
  { package: "@caretive/caret-cli", versions: ["0.0.2"] },
  { package: "@chtijs/eslint-config", versions: ["1.0.1"] },
  { package: "@clausehq/flows-step-httprequest", versions: ["0.1.14"] },
  { package: "@clausehq/flows-step-jsontoxml", versions: ["0.1.14"] },
  { package: "@clausehq/flows-step-mqtt", versions: ["0.1.14"] },
  { package: "@clausehq/flows-step-sendgridemail", versions: ["0.1.14"] },
  { package: "@clausehq/flows-step-taskscreateurl", versions: ["0.1.14"] },
  { package: "@cllbk/ghl", versions: ["1.3.1"] },
  { package: "@commute/bloom", versions: ["1.0.3"] },
  { package: "@commute/market-data", versions: ["1.0.2"] },
  { package: "@commute/market-data-chartjs", versions: ["2.3.1"] },
  { package: "@dev-blinq/ai-qa-logic", versions: ["1.0.19"] },
  { package: "@dev-blinq/blinqioclient", versions: ["1.0.21"] },
  { package: "@dev-blinq/cucumber-js", versions: ["1.0.131"] },
  { package: "@dev-blinq/cucumber_client", versions: ["1.0.738"] },
  { package: "@dev-blinq/ui-systems", versions: ["1.0.93"] },
  { package: "@ensdomains/address-encoder", versions: ["1.1.5"] },
  { package: "@ensdomains/blacklist", versions: ["1.0.1"] },
  { package: "@ensdomains/buffer", versions: ["0.1.2"] },
  { package: "@ensdomains/ccip-read-cf-worker", versions: ["0.0.4"] },
  { package: "@ensdomains/ccip-read-dns-gateway", versions: ["0.1.1"] },
  { package: "@ensdomains/ccip-read-router", versions: ["0.0.7"] },
  { package: "@ensdomains/ccip-read-worker-viem", versions: ["0.0.4"] },
  { package: "@ensdomains/content-hash", versions: ["3.0.1"] },
  { package: "@ensdomains/curvearithmetics", versions: ["1.0.1"] },
  { package: "@ensdomains/cypress-metamask", versions: ["1.2.1"] },
  { package: "@ensdomains/dnsprovejs", versions: ["0.5.3"] },
  { package: "@ensdomains/dnssec-oracle-anchors", versions: ["0.0.2"] },
  { package: "@ensdomains/dnssecoraclejs", versions: ["0.2.9"] },
  { package: "@ensdomains/durin", versions: ["0.1.2"] },
  { package: "@ensdomains/durin-middleware", versions: ["0.0.2"] },
  { package: "@ensdomains/ens-archived-contracts", versions: ["0.0.3"] },
  { package: "@ensdomains/ens-avatar", versions: ["1.0.4"] },
  { package: "@ensdomains/ens-contracts", versions: ["1.6.1"] },
  { package: "@ensdomains/ens-test-env", versions: ["1.0.2"] },
  { package: "@ensdomains/ens-validation", versions: ["0.1.1"] },
  { package: "@ensdomains/ensjs", versions: ["4.0.3"] },
  { package: "@ensdomains/ensjs-react", versions: ["0.0.5"] },
  { package: "@ensdomains/eth-ens-namehash", versions: ["2.0.16"] },
  { package: "@ensdomains/hackathon-registrar", versions: ["1.0.5"] },
  { package: "@ensdomains/hardhat-chai-matchers-viem", versions: ["0.1.15"] },
  { package: "@ensdomains/hardhat-toolbox-viem-extended", versions: ["0.0.6"] },
  { package: "@ensdomains/mock", versions: ["2.1.52"] },
  { package: "@ensdomains/name-wrapper", versions: ["1.0.1"] },
  { package: "@ensdomains/offchain-resolver-contracts", versions: ["0.2.2"] },
  { package: "@ensdomains/op-resolver-contracts", versions: ["0.0.2"] },
  { package: "@ensdomains/react-ens-address", versions: ["0.0.32"] },
  { package: "@ensdomains/renewal", versions: ["0.0.13"] },
  { package: "@ensdomains/renewal-widget", versions: ["0.1.10"] },
  { package: "@ensdomains/reverse-records", versions: ["1.0.1"] },
  { package: "@ensdomains/server-analytics", versions: ["0.0.2"] },
  { package: "@ensdomains/solsha1", versions: ["0.0.4"] },
  { package: "@ensdomains/subdomain-registrar", versions: ["0.2.4"] },
  { package: "@ensdomains/test-utils", versions: ["1.3.1"] },
  { package: "@ensdomains/thorin", versions: ["0.6.51"] },
  { package: "@ensdomains/ui", versions: ["3.4.6"] },
  { package: "@ensdomains/unicode-confusables", versions: ["0.1.1"] },
  { package: "@ensdomains/unruggable-gateways", versions: ["0.0.3"] },
  { package: "@ensdomains/vite-plugin-i18next-loader", versions: ["4.0.4"] },
  { package: "@ensdomains/web3modal", versions: ["1.10.2"] },
  { package: "@everreal/react-charts", versions: ["2.0.2", "2.0.1"] },
  { package: "@everreal/validate-esmoduleinterop-imports", versions: ["1.4.5", "1.4.4"] },
  { package: "@everreal/web-analytics", versions: ["0.0.1", "0.0.2"] },
  { package: "@faq-component/core", versions: ["0.0.4"] },
  { package: "@faq-component/react", versions: ["1.0.1"] },
  { package: "@fishingbooker/browser-sync-plugin", versions: ["1.0.5"] },
  { package: "@fishingbooker/react-loader", versions: ["1.0.7"] },
  { package: "@fishingbooker/react-pagination", versions: ["2.0.6"] },
  { package: "@fishingbooker/react-raty", versions: ["2.0.1"] },
  { package: "@fishingbooker/react-swiper", versions: ["0.1.5"] },
  { package: "@hapheus/n8n-nodes-pgp", versions: ["1.5.1"] },
  { package: "@hover-design/core", versions: ["0.0.1"] },
  { package: "@hover-design/react", versions: ["0.2.1"] },
  { package: "@huntersofbook/auth-vue", versions: ["0.4.2"] },
  { package: "@huntersofbook/core", versions: ["0.5.1"] },
  { package: "@huntersofbook/core-nuxt", versions: ["0.4.2"] },
  { package: "@huntersofbook/form-naiveui", versions: ["0.5.1"] },
  { package: "@huntersofbook/i18n", versions: ["0.8.2"] },
  { package: "@huntersofbook/ui", versions: ["0.5.1"] },
  { package: "@hyperlook/telemetry-sdk", versions: ["1.0.19"] },
  { package: "@ifelsedeveloper/protocol-contracts-svm-idl", versions: ["0.1.2", "0.1.3"] },
  { package: "@ifings/design-system", versions: ["4.9.2"] },
  { package: "@ifings/metatron3", versions: ["0.1.5"] },
  { package: "@jayeshsadhwani/telemetry-sdk", versions: ["1.0.14"] },
  { package: "@kvytech/cli", versions: ["0.0.7"] },
  { package: "@kvytech/components", versions: ["0.0.2"] },
  { package: "@kvytech/habbit-e2e-test", versions: ["0.0.2"] },
  { package: "@kvytech/medusa-plugin-announcement", versions: ["0.0.8"] },
  { package: "@kvytech/medusa-plugin-management", versions: ["0.0.5"] },
  { package: "@kvytech/medusa-plugin-newsletter", versions: ["0.0.5"] },
  { package: "@kvytech/medusa-plugin-product-reviews", versions: ["0.0.9"] },
  { package: "@kvytech/medusa-plugin-promotion", versions: ["0.0.2"] },
  { package: "@kvytech/web", versions: ["0.0.2"] },
  { package: "@lessondesk/api-client", versions: ["9.12.2", "9.12.3"] },
  { package: "@lessondesk/babel-preset", versions: ["1.0.1"] },
  { package: "@lessondesk/electron-group-api-client", versions: ["1.0.3"] },
  { package: "@lessondesk/eslint-config", versions: ["1.4.2"] },
  { package: "@lessondesk/material-icons", versions: ["1.0.3"] },
  { package: "@lessondesk/react-table-context", versions: ["2.0.4"] },
  { package: "@lessondesk/schoolbus", versions: ["5.2.2", "5.2.3"] },
  { package: "@livecms/live-edit", versions: ["0.0.32"] },
  { package: "@livecms/nuxt-live-edit", versions: ["1.9.2"] },
  { package: "@lokeswari-satyanarayanan/rn-zustand-expo-template", versions: ["1.0.9"] },
  { package: "@louisle2/core", versions: ["1.0.1"] },
  { package: "@louisle2/cortex-js", versions: ["0.1.6"] },
  { package: "@lpdjs/firestore-repo-service", versions: ["1.0.1"] },
  { package: "@lui-ui/lui-nuxt", versions: ["0.1.1"] },
  { package: "@lui-ui/lui-tailwindcss", versions: ["0.1.2"] },
  { package: "@lui-ui/lui-vue", versions: ["1.0.13"] },
  { package: "@markvivanco/app-version-checker", versions: ["1.0.2", "1.0.1"] },
  { package: "@mcp-use/cli", versions: ["2.2.7", "2.2.6"] },
  { package: "@mcp-use/inspector", versions: ["0.6.3", "0.6.2"] },
  { package: "@mcp-use/mcp-use", versions: ["1.0.2", "1.0.1"] },
  { package: "@micado-digital/stadtmarketing-kufstein-external", versions: ["1.9.1"] },
  { package: "@mizzle-dev/orm", versions: ["0.0.2"] },
  { package: "@mparpaillon/connector-parse", versions: ["1.0.1"] },
  { package: "@mparpaillon/imagesloaded", versions: ["4.1.2"] },
  { package: "@mparpaillon/page", versions: ["1.0.1"] },
  { package: "@ntnx/passport-wso2", versions: ["0.0.3"] },
  { package: "@ntnx/t", versions: ["0.0.101"] },
  { package: "@oku-ui/accordion", versions: ["0.6.2"] },
  { package: "@oku-ui/alert-dialog", versions: ["0.6.2"] },
  { package: "@oku-ui/arrow", versions: ["0.6.2"] },
  { package: "@oku-ui/aspect-ratio", versions: ["0.6.2"] },
  { package: "@oku-ui/avatar", versions: ["0.6.2"] },
  { package: "@oku-ui/checkbox", versions: ["0.6.3"] },
  { package: "@oku-ui/collapsible", versions: ["0.6.2"] },
  { package: "@oku-ui/collection", versions: ["0.6.2"] },
  { package: "@oku-ui/dialog", versions: ["0.6.2"] },
  { package: "@oku-ui/direction", versions: ["0.6.2"] },
  { package: "@oku-ui/dismissable-layer", versions: ["0.6.2"] },
  { package: "@oku-ui/focus-guards", versions: ["0.6.2"] },
  { package: "@oku-ui/focus-scope", versions: ["0.6.2"] },
  { package: "@oku-ui/hover-card", versions: ["0.6.2"] },
  { package: "@oku-ui/label", versions: ["0.6.2"] },
  { package: "@oku-ui/menu", versions: ["0.6.2"] },
  { package: "@oku-ui/motion", versions: ["0.4.4"] },
  { package: "@oku-ui/motion-nuxt", versions: ["0.2.2"] },
  { package: "@oku-ui/popover", versions: ["0.6.2"] },
  { package: "@oku-ui/popper", versions: ["0.6.2"] },
  { package: "@oku-ui/portal", versions: ["0.6.2"] },
  { package: "@oku-ui/presence", versions: ["0.6.2"] },
  { package: "@oku-ui/primitive", versions: ["0.6.2"] },
  { package: "@oku-ui/primitives", versions: ["0.7.9"] },
  { package: "@oku-ui/primitives-nuxt", versions: ["0.3.1"] },
  { package: "@oku-ui/progress", versions: ["0.6.2"] },
  { package: "@oku-ui/provide", versions: ["0.6.2"] },
  { package: "@oku-ui/radio-group", versions: ["0.6.2"] },
  { package: "@oku-ui/roving-focus", versions: ["0.6.2"] },
  { package: "@oku-ui/scroll-area", versions: ["0.6.2"] },
  { package: "@oku-ui/separator", versions: ["0.6.2"] },
  { package: "@oku-ui/slider", versions: ["0.6.2"] },
  { package: "@oku-ui/slot", versions: ["0.6.2"] },
  { package: "@oku-ui/switch", versions: ["0.6.2"] },
  { package: "@oku-ui/tabs", versions: ["0.6.2"] },
  { package: "@oku-ui/toast", versions: ["0.6.2"] },
  { package: "@oku-ui/toggle", versions: ["0.6.2"] },
  { package: "@oku-ui/toggle-group", versions: ["0.6.2"] },
  { package: "@oku-ui/toolbar", versions: ["0.6.2"] },
  { package: "@oku-ui/tooltip", versions: ["0.6.2"] },
  { package: "@oku-ui/use-composable", versions: ["0.6.2"] },
  { package: "@oku-ui/utils", versions: ["0.6.2"] },
  { package: "@oku-ui/visually-hidden", versions: ["0.6.2"] },
  { package: "@orbitgtbelgium/mapbox-gl-draw-cut-polygon-mode", versions: ["2.0.5"] },
  { package: "@orbitgtbelgium/mapbox-gl-draw-scale-rotate-mode", versions: ["1.1.1"] },
  { package: "@orbitgtbelgium/orbit-components", versions: ["1.2.9"] },
  { package: "@orbitgtbelgium/time-slider", versions: ["1.0.187"] },
  { package: "@osmanekrem/bmad", versions: ["1.0.6"] },
  { package: "@osmanekrem/error-handler", versions: ["1.2.2"] },
  { package: "@pergel/cli", versions: ["0.11.1"] },
  { package: "@pergel/module-box", versions: ["0.6.1"] },
  { package: "@pergel/module-graphql", versions: ["0.6.1"] },
  { package: "@pergel/module-ui", versions: ["0.0.9"] },
  { package: "@pergel/nuxt", versions: ["0.25.5"] },
  { package: "@posthog/agent", versions: ["1.24.1"] },
  { package: "@posthog/ai", versions: ["7.1.2"] },
  { package: "@posthog/automatic-cohorts-plugin", versions: ["0.0.8"] },
  { package: "@posthog/bitbucket-release-tracker", versions: ["0.0.8"] },
  { package: "@posthog/cli", versions: ["0.5.15"] },
  { package: "@posthog/clickhouse", versions: ["1.7.1"] },
  { package: "@posthog/core", versions: ["1.5.6"] },
  { package: "@posthog/currency-normalization-plugin", versions: ["0.0.8"] },
  { package: "@posthog/customerio-plugin", versions: ["0.0.8"] },
  { package: "@posthog/databricks-plugin", versions: ["0.0.8"] },
  { package: "@posthog/drop-events-on-property-plugin", versions: ["0.0.8"] },
  { package: "@posthog/event-sequence-timer-plugin", versions: ["0.0.8"] },
  { package: "@posthog/filter-out-plugin", versions: ["0.0.8"] },
  { package: "@posthog/first-time-event-tracker", versions: ["0.0.8"] },
  { package: "@posthog/geoip-plugin", versions: ["0.0.8"] },
  { package: "@posthog/github-release-tracking-plugin", versions: ["0.0.8"] },
  { package: "@posthog/gitub-star-sync-plugin", versions: ["0.0.8"] },
  { package: "@posthog/heartbeat-plugin", versions: ["0.0.8"] },
  { package: "@posthog/hedgehog-mode", versions: ["0.0.42"] },
  { package: "@posthog/icons", versions: ["0.36.1"] },
  { package: "@posthog/ingestion-alert-plugin", versions: ["0.0.8"] },
  { package: "@posthog/intercom-plugin", versions: ["0.0.8"] },
  { package: "@posthog/kinesis-plugin", versions: ["0.0.8"] },
  { package: "@posthog/laudspeaker-plugin", versions: ["0.0.8"] },
  { package: "@posthog/lemon-ui", versions: ["0.0.1"] },
  { package: "@posthog/maxmind-plugin", versions: ["0.1.6"] },
  { package: "@posthog/migrator3000-plugin", versions: ["0.0.8"] },
  { package: "@posthog/netdata-event-processing", versions: ["0.0.8"] },
  { package: "@posthog/nextjs", versions: ["0.0.3"] },
  { package: "@posthog/nextjs-config", versions: ["1.5.1"] },
  { package: "@posthog/nuxt", versions: ["1.2.9"] },
  { package: "@posthog/pagerduty-plugin", versions: ["0.0.8"] },
  { package: "@posthog/piscina", versions: ["3.2.1"] },
  { package: "@posthog/plugin-contrib", versions: ["0.0.6"] },
  { package: "@posthog/plugin-server", versions: ["1.10.8"] },
  { package: "@posthog/plugin-unduplicates", versions: ["0.0.8"] },
  { package: "@posthog/postgres-plugin", versions: ["0.0.8"] },
  { package: "@posthog/react-rrweb-player", versions: ["1.1.4"] },
  { package: "@posthog/rrdom", versions: ["0.0.31"] },
  { package: "@posthog/rrweb", versions: ["0.0.31"] },
  { package: "@posthog/rrweb-player", versions: ["0.0.31"] },
  { package: "@posthog/rrweb-record", versions: ["0.0.31"] },
  { package: "@posthog/rrweb-replay", versions: ["0.0.19"] },
  { package: "@posthog/rrweb-snapshot", versions: ["0.0.31"] },
  { package: "@posthog/rrweb-utils", versions: ["0.0.31"] },
  { package: "@posthog/sendgrid-plugin", versions: ["0.0.8"] },
  { package: "@posthog/siphash", versions: ["1.1.2"] },
  { package: "@posthog/snowflake-export-plugin", versions: ["0.0.8"] },
  { package: "@posthog/taxonomy-plugin", versions: ["0.0.8"] },
  { package: "@posthog/twilio-plugin", versions: ["0.0.8"] },
  { package: "@posthog/twitter-followers-plugin", versions: ["0.0.8"] },
  { package: "@posthog/url-normalizer-plugin", versions: ["0.0.8"] },
  { package: "@posthog/variance-plugin", versions: ["0.0.8"] },
  { package: "@posthog/web-dev-server", versions: ["1.0.5"] },
  { package: "@posthog/wizard", versions: ["1.18.1"] },
  { package: "@posthog/zendesk-plugin", versions: ["0.0.8"] },
  { package: "@postman/aether-icons", versions: ["2.23.2", "2.23.3", "2.23.4"] },
  { package: "@postman/csv-parse", versions: ["4.0.3", "4.0.5", "4.0.4"] },
  { package: "@postman/final-node-keytar", versions: ["7.9.3", "7.9.1", "7.9.2"] },
  { package: "@postman/mcp-ui-client", versions: ["5.5.2", "5.5.3", "5.5.1"] },
  { package: "@postman/node-keytar", versions: ["7.9.4", "7.9.5", "7.9.6"] },
  { package: "@postman/pm-bin-linux-x64", versions: ["1.24.3", "1.24.5", "1.24.4"] },
  { package: "@postman/pm-bin-macos-arm64", versions: ["1.24.3", "1.24.5", "1.24.4"] },
  { package: "@postman/pm-bin-macos-x64", versions: ["1.24.3", "1.24.5", "1.24.4"] },
  { package: "@postman/pm-bin-windows-x64", versions: ["1.24.3", "1.24.5", "1.24.4"] },
  { package: "@postman/postman-collection-fork", versions: ["4.3.3", "4.3.5", "4.3.4"] },
  { package: "@postman/postman-mcp-cli", versions: ["1.0.4", "1.0.5", "1.0.3"] },
  { package: "@postman/postman-mcp-server", versions: ["2.4.12", "2.4.10", "2.4.11"] },
  { package: "@postman/pretty-ms", versions: ["6.1.2", "6.1.3", "6.1.1"] },
  { package: "@postman/secret-scanner-wasm", versions: ["2.1.4", "2.1.3", "2.1.2"] },
  { package: "@postman/tunnel-agent", versions: ["0.6.5", "0.6.7", "0.6.6"] },
  { package: "@postman/wdio-allure-reporter", versions: ["0.0.7", "0.0.8", "0.0.9"] },
  { package: "@postman/wdio-junit-reporter", versions: ["0.0.4", "0.0.5", "0.0.6"] },
  { package: "@pradhumngautam/common-app", versions: ["1.0.2"] },
  { package: "@productdevbook/animejs-vue", versions: ["0.2.1"] },
  { package: "@productdevbook/auth", versions: ["0.2.2"] },
  { package: "@productdevbook/chatwoot", versions: ["2.0.1"] },
  { package: "@productdevbook/motion", versions: ["1.0.4"] },
  { package: "@productdevbook/ts-i18n", versions: ["1.4.2"] },
  { package: "@pruthvi21/use-debounce", versions: ["1.0.3"] },
  { package: "@quick-start-soft/quick-document-translator", versions: ["1.4.2511142126"] },
  { package: "@quick-start-soft/quick-git-clean-markdown", versions: ["1.4.2511142126"] },
  { package: "@quick-start-soft/quick-markdown", versions: ["1.4.2511142126"] },
  { package: "@quick-start-soft/quick-markdown-compose", versions: ["1.4.2506300029"] },
  { package: "@quick-start-soft/quick-markdown-image", versions: ["1.4.2511142126"] },
  { package: "@quick-start-soft/quick-markdown-print", versions: ["1.4.2511142126"] },
  { package: "@quick-start-soft/quick-markdown-translator", versions: ["1.4.2509202331"] },
  { package: "@quick-start-soft/quick-remove-image-background", versions: ["1.4.2511142126"] },
  { package: "@quick-start-soft/quick-task-refine", versions: ["1.4.2511142126"] },
  { package: "@relyt/claude-context-core", versions: ["0.1.1"] },
  { package: "@relyt/claude-context-mcp", versions: ["0.1.1"] },
  { package: "@relyt/mcp-server-relytone", versions: ["0.0.3"] },
  { package: "@sameepsi/sor", versions: ["1.0.3"] },
  { package: "@sameepsi/sor2", versions: ["2.0.2"] },
  { package: "@seezo/sdr-mcp-server", versions: ["0.0.5"] },
  { package: "@seung-ju/next", versions: ["0.0.2"] },
  { package: "@seung-ju/openapi-generator", versions: ["0.0.4"] },
  { package: "@seung-ju/react-hooks", versions: ["0.0.2"] },
  { package: "@seung-ju/react-native-action-sheet", versions: ["0.2.1"] },
  { package: "@silgi/better-auth", versions: ["0.8.1"] },
  { package: "@silgi/drizzle", versions: ["0.8.4"] },
  { package: "@silgi/ecosystem", versions: ["0.7.6"] },
  { package: "@silgi/graphql", versions: ["0.7.15"] },
  { package: "@silgi/module-builder", versions: ["0.8.8"] },
  { package: "@silgi/openapi", versions: ["0.7.4"] },
  { package: "@silgi/permission", versions: ["0.6.8"] },
  { package: "@silgi/ratelimit", versions: ["0.2.1"] },
  { package: "@silgi/scalar", versions: ["0.6.2"] },
  { package: "@silgi/yoga", versions: ["0.7.1"] },
  { package: "@sme-ui/aoma-vevasound-metadata-lib", versions: ["0.1.3"] },
  { package: "@strapbuild/react-native-date-time-picker", versions: ["2.0.4"] },
  { package: "@strapbuild/react-native-perspective-image-cropper", versions: ["0.4.15"] },
  { package: "@strapbuild/react-native-perspective-image-cropper-2", versions: ["0.4.7"] },
  { package: "@strapbuild/react-native-perspective-image-cropper-poojan31", versions: ["0.4.6"] },
  { package: "@suraj_h/medium-common", versions: ["1.0.5"] },
  { package: "@thedelta/eslint-config", versions: ["1.0.2"] },
  { package: "@tiaanduplessis/json", versions: ["2.0.2", "2.0.3"] },
  { package: "@tiaanduplessis/react-progressbar", versions: ["1.0.2", "1.0.1"] },
  { package: "@trackstar/angular-trackstar-link", versions: ["1.0.2"] },
  { package: "@trackstar/react-trackstar-link", versions: ["2.0.21"] },
  { package: "@trackstar/react-trackstar-link-upgrade", versions: ["1.1.10"] },
  { package: "@trackstar/test-angular-package", versions: ["0.0.9"] },
  { package: "@trackstar/test-package", versions: ["1.1.5"] },
  { package: "@trefox/sleekshop-js", versions: ["0.1.6"] },
  { package: "@trigo/atrix", versions: ["7.0.1"] },
  { package: "@trigo/atrix-acl", versions: ["4.0.2"] },
  { package: "@trigo/atrix-elasticsearch", versions: ["2.0.1"] },
  { package: "@trigo/atrix-mongoose", versions: ["1.0.2"] },
  { package: "@trigo/atrix-orientdb", versions: ["1.0.2"] },
  { package: "@trigo/atrix-postgres", versions: ["1.0.3"] },
  { package: "@trigo/atrix-pubsub", versions: ["4.0.3"] },
  { package: "@trigo/atrix-redis", versions: ["1.0.2"] },
  { package: "@trigo/atrix-soap", versions: ["1.0.2"] },
  { package: "@trigo/atrix-swagger", versions: ["3.0.1"] },
  { package: "@trigo/bool-expressions", versions: ["4.1.3"] },
  { package: "@trigo/eslint-config-trigo", versions: ["3.3.1"] },
  { package: "@trigo/fsm", versions: ["3.4.2"] },
  { package: "@trigo/hapi-auth-signedlink", versions: ["1.3.1"] },
  { package: "@trigo/jsdt", versions: ["0.2.1"] },
  { package: "@trigo/keycloak-api", versions: ["1.3.1"] },
  { package: "@trigo/node-soap", versions: ["0.5.4"] },
  { package: "@trigo/pathfinder-ui-css", versions: ["0.1.1"] },
  { package: "@trigo/trigo-hapijs", versions: ["5.0.1"] },
  { package: "@trpc-rate-limiter/cloudflare", versions: ["0.1.4"] },
  { package: "@trpc-rate-limiter/hono", versions: ["0.1.4"] },
  { package: "@varsityvibe/api-client", versions: ["1.3.36", "1.3.37"] },
  { package: "@varsityvibe/utils", versions: ["5.0.6"] },
  { package: "@varsityvibe/validation-schemas", versions: ["0.6.7", "0.6.8"] },
  { package: "@viapip/eslint-config", versions: ["0.2.4"] },
  { package: "@vishadtyagi/full-year-calendar", versions: ["0.1.11"] },
  { package: "@voiceflow/alexa-types", versions: ["2.15.60", "2.15.61"] },
  { package: "@voiceflow/anthropic", versions: ["0.4.4", "0.4.5"] },
  { package: "@voiceflow/api-sdk", versions: ["3.28.59", "3.28.58"] },
  { package: "@voiceflow/backend-utils", versions: ["5.0.1", "5.0.2"] },
  { package: "@voiceflow/base-types", versions: ["2.136.3", "2.136.2"] },
  { package: "@voiceflow/body-parser", versions: ["1.21.3", "1.21.2"] },
  { package: "@voiceflow/chat-types", versions: ["2.14.59", "2.14.58"] },
  { package: "@voiceflow/circleci-config-sdk-orb-import", versions: ["0.2.1", "0.2.2"] },
  { package: "@voiceflow/commitlint-config", versions: ["2.6.2", "2.6.1"] },
  { package: "@voiceflow/common", versions: ["8.9.1", "8.9.2"] },
  { package: "@voiceflow/default-prompt-wrappers", versions: ["1.7.4", "1.7.3"] },
  { package: "@voiceflow/dependency-cruiser-config", versions: ["1.8.11", "1.8.12"] },
  { package: "@voiceflow/dtos-interact", versions: ["1.40.2", "1.40.1"] },
  { package: "@voiceflow/encryption", versions: ["0.3.2", "0.3.3"] },
  { package: "@voiceflow/eslint-config", versions: ["7.16.4", "7.16.5"] },
  { package: "@voiceflow/eslint-plugin", versions: ["1.6.2", "1.6.1"] },
  { package: "@voiceflow/exception", versions: ["1.10.1", "1.10.2"] },
  { package: "@voiceflow/fetch", versions: ["1.11.1", "1.11.2"] },
  { package: "@voiceflow/general-types", versions: ["3.2.22", "3.2.23"] },
  { package: "@voiceflow/git-branch-check", versions: ["1.4.3", "1.4.4"] },
  { package: "@voiceflow/google-dfes-types", versions: ["2.17.12", "2.17.13"] },
  { package: "@voiceflow/google-types", versions: ["2.21.12", "2.21.13"] },
  { package: "@voiceflow/husky-config", versions: ["1.3.2", "1.3.1"] },
  { package: "@voiceflow/logger", versions: ["2.4.3", "2.4.2"] },
  { package: "@voiceflow/metrics", versions: ["1.5.2", "1.5.1"] },
  { package: "@voiceflow/natural-language-commander", versions: ["0.5.2", "0.5.3"] },
  { package: "@voiceflow/nestjs-common", versions: ["2.75.3", "2.75.2"] },
  { package: "@voiceflow/nestjs-mongodb", versions: ["1.3.2", "1.3.1"] },
  { package: "@voiceflow/nestjs-rate-limit", versions: ["1.3.2", "1.3.3"] },
  { package: "@voiceflow/nestjs-redis", versions: ["1.3.2", "1.3.1"] },
  { package: "@voiceflow/nestjs-timeout", versions: ["1.3.2", "1.3.1"] },
  { package: "@voiceflow/npm-package-json-lint-config", versions: ["1.1.2", "1.1.1"] },
  { package: "@voiceflow/openai", versions: ["3.2.3", "3.2.2"] },
  { package: "@voiceflow/pino", versions: ["6.11.4", "6.11.3"] },
  { package: "@voiceflow/pino-pretty", versions: ["4.4.1", "4.4.2"] },
  { package: "@voiceflow/prettier-config", versions: ["1.10.1", "1.10.2"] },
  { package: "@voiceflow/react-chat", versions: ["1.65.3", "1.65.4"] },
  { package: "@voiceflow/runtime", versions: ["1.29.2", "1.29.1"] },
  { package: "@voiceflow/runtime-client-js", versions: ["1.17.2", "1.17.3"] },
  { package: "@voiceflow/sdk-runtime", versions: ["1.43.2", "1.43.1"] },
  { package: "@voiceflow/secrets-provider", versions: ["1.9.2", "1.9.3"] },
  { package: "@voiceflow/semantic-release-config", versions: ["1.4.2", "1.4.1"] },
  { package: "@voiceflow/serverless-plugin-typescript", versions: ["2.1.8", "2.1.7"] },
  { package: "@voiceflow/slate-serializer", versions: ["1.7.4", "1.7.3"] },
  { package: "@voiceflow/stitches-react", versions: ["2.3.3", "2.3.2"] },
  { package: "@voiceflow/storybook-config", versions: ["1.2.3", "1.2.2"] },
  { package: "@voiceflow/stylelint-config", versions: ["1.1.2", "1.1.1"] },
  { package: "@voiceflow/test-common", versions: ["2.1.1", "2.1.2"] },
  { package: "@voiceflow/tsconfig", versions: ["1.12.1", "1.12.2"] },
  { package: "@voiceflow/tsconfig-paths", versions: ["1.1.5", "1.1.4"] },
  { package: "@voiceflow/utils-designer", versions: ["1.74.20", "1.74.19"] },
  { package: "@voiceflow/verror", versions: ["1.1.5", "1.1.4"] },
  { package: "@voiceflow/vite-config", versions: ["2.6.2", "2.6.3"] },
  { package: "@voiceflow/vitest-config", versions: ["1.10.3", "1.10.2"] },
  { package: "@voiceflow/voice-types", versions: ["2.10.58", "2.10.59"] },
  { package: "@voiceflow/voiceflow-types", versions: ["3.32.45", "3.32.46"] },
  { package: "@voiceflow/widget", versions: ["1.7.18", "1.7.19"] },
  { package: "@vucod/email", versions: ["0.0.3"] },
  { package: "@zapier/ai-actions", versions: ["0.1.18", "0.1.19", "0.1.20"] },
  { package: "@zapier/ai-actions-react", versions: ["0.1.13", "0.1.12", "0.1.14"] },
  { package: "@zapier/babel-preset-zapier", versions: ["6.4.2", "6.4.1", "6.4.3"] },
  { package: "@zapier/browserslist-config-zapier", versions: ["1.0.4", "1.0.5", "1.0.3"] },
  { package: "@zapier/eslint-plugin-zapier", versions: ["11.0.5", "11.0.3", "11.0.4"] },
  { package: "@zapier/mcp-integration", versions: ["3.0.3", "3.0.1", "3.0.2"] },
  { package: "@zapier/secret-scrubber", versions: ["1.1.5", "1.1.3", "1.1.4"] },
  { package: "@zapier/spectral-api-ruleset", versions: ["1.9.3", "1.9.2", "1.9.1"] },
  { package: "@zapier/stubtree", versions: ["0.1.4", "0.1.3", "0.1.2"] },
  { package: "@zapier/zapier-sdk", versions: ["0.15.7", "0.15.6", "0.15.5"] },
  { package: "ai-crowl-shield", versions: ["1.0.7"] },
  { package: "arc-cli-fc", versions: ["1.0.1"] },
  { package: "asciitranslator", versions: ["1.0.3"] },
  { package: "asyncapi-preview", versions: ["1.0.2", "1.0.1"] },
  { package: "atrix", versions: ["1.0.1"] },
  { package: "atrix-mongoose", versions: ["1.0.1"] },
  { package: "automation_model", versions: ["1.0.491"] },
  { package: "avvvatars-vue", versions: ["1.1.2"] },
  { package: "axios-builder", versions: ["1.2.1"] },
  { package: "axios-cancelable", versions: ["1.0.2", "1.0.1"] },
  { package: "axios-timed", versions: ["1.0.2", "1.0.1"] },
  { package: "babel-preset-kinvey-flex-service", versions: ["0.1.1"] },
  { package: "barebones-css", versions: ["1.1.3", "1.1.4"] },
  { package: "benmostyn-frame-print", versions: ["1.0.1"] },
  { package: "best_gpio_controller", versions: ["1.0.10"] },
  { package: "better-auth-nuxt", versions: ["0.0.10"] },
  { package: "better-queue-nedb", versions: ["0.1.5"] },
  { package: "bidirectional-adapter", versions: ["1.2.3", "1.2.2", "1.2.5", "1.2.4"] },
  { package: "blinqio-executions-cli", versions: ["1.0.41"] },
  { package: "blob-to-base64", versions: ["1.0.3"] },
  { package: "bool-expressions", versions: ["0.1.2"] },
  { package: "buffered-interpolation-babylon6", versions: ["0.2.8"] },
  { package: "bun-plugin-httpfile", versions: ["0.1.1"] },
  { package: "bytecode-checker-cli", versions: ["1.0.10", "1.0.9", "1.0.8", "1.0.11"] },
  { package: "bytes-to-x", versions: ["1.0.1"] },
  { package: "calc-loan-interest", versions: ["1.0.4"] },
  { package: "capacitor-plugin-apptrackingios", versions: ["0.0.21"] },
  { package: "capacitor-plugin-purchase", versions: ["0.1.1"] },
  { package: "capacitor-plugin-scgssigninwithgoogle", versions: ["0.0.5"] },
  { package: "capacitor-purchase-history", versions: ["0.0.10"] },
  { package: "capacitor-voice-recorder-wav", versions: ["6.0.3"] },
  { package: "ceviz", versions: ["0.0.5"] },
  { package: "chrome-extension-downloads", versions: ["0.0.3", "0.0.4"] },
  { package: "claude-token-updater", versions: ["1.0.3"] },
  { package: "coinmarketcap-api", versions: ["3.1.3", "3.1.2"] },
  { package: "colors-regex", versions: ["2.0.1"] },
  { package: "command-irail", versions: ["0.5.4"] },
  { package: "compare-obj", versions: ["1.1.2", "1.1.1"] },
  { package: "composite-reducer", versions: ["1.0.4", "1.0.5", "1.0.2", "1.0.3"] },
  { package: "count-it-down", versions: ["1.0.2", "1.0.1"] },
  { package: "cpu-instructions", versions: ["0.0.14"] },
  { package: "create-director-app", versions: ["0.1.1"] },
  { package: "create-glee-app", versions: ["0.2.3", "0.2.2"] },
  { package: "create-hardhat3-app", versions: ["1.1.2", "1.1.3", "1.1.1", "1.1.4"] },
  { package: "create-kinvey-flex-service", versions: ["0.2.1"] },
  { package: "create-mcp-use-app", versions: ["0.5.4", "0.5.3"] },
  { package: "create-silgi", versions: ["0.3.1"] },
  { package: "crypto-addr-codec", versions: ["0.1.9"] },
  { package: "css-dedoupe", versions: ["0.1.2"] },
  { package: "csv-tool-cli", versions: ["1.2.1"] },
  { package: "dashboard-empty-state", versions: ["1.0.3"] },
  { package: "designstudiouiux", versions: ["1.0.1"] },
  { package: "devstart-cli", versions: ["1.0.6"] },
  { package: "dialogflow-es", versions: ["1.1.2", "1.1.3", "1.1.1", "1.1.4"] },
  { package: "discord-bot-server", versions: ["0.1.2"] },
  { package: "docusaurus-plugin-vanilla-extract", versions: ["1.0.3"] },
  { package: "dont-go", versions: ["1.1.2"] },
  { package: "dotnet-template", versions: ["0.0.3", "0.0.4"] },
  { package: "drop-events-on-property-plugin", versions: ["0.0.2"] },
  { package: "easypanel-sdk", versions: ["0.3.2"] },
  { package: "electron-volt", versions: ["0.0.2"] },
  { package: "email-deliverability-tester", versions: ["1.1.1"] },
  { package: "enforce-branch-name", versions: ["1.1.3"] },
  { package: "esbuild-plugin-brotli", versions: ["0.2.1"] },
  { package: "esbuild-plugin-eta", versions: ["0.1.1"] },
  { package: "esbuild-plugin-httpfile", versions: ["0.4.1"] },
  { package: "eslint-config-kinvey-flex-service", versions: ["0.1.1"] },
  { package: "eslint-config-nitpicky", versions: ["4.0.1"] },
  { package: "eslint-config-trigo", versions: ["22.0.2"] },
  { package: "eslint-config-zeallat-base", versions: ["1.0.4"] },
  { package: "ethereum-ens", versions: ["0.8.1"] },
  { package: "evm-checkcode-cli", versions: ["1.0.14", "1.0.12", "1.0.15", "1.0.13"] },
  { package: "exact-ticker", versions: ["0.3.5"] },
  { package: "expo-audio-session", versions: ["0.2.1"] },
  { package: "expo-router-on-rails", versions: ["0.0.4"] },
  { package: "express-starter-template", versions: ["1.0.10"] },
  { package: "expressos", versions: ["1.1.3"] },
  { package: "fat-fingered", versions: ["1.0.2", "1.0.1"] },
  { package: "feature-flip", versions: ["1.0.2", "1.0.1"] },
  { package: "firestore-search-engine", versions: ["1.2.3"] },
  { package: "fittxt", versions: ["1.0.3", "1.0.2"] },
  { package: "flapstacks", versions: ["1.0.2", "1.0.1"] },
  { package: "flatten-unflatten", versions: ["1.0.2", "1.0.1"] },
  { package: "formik-error-focus", versions: ["2.0.1"] },
  { package: "formik-store", versions: ["1.0.1"] },
  { package: "frontity-starter-theme", versions: ["1.0.1"] },
  { package: "fuzzy-finder", versions: ["1.0.6", "1.0.5"] },
  { package: "gate-evm-check-code2", versions: ["2.0.6", "2.0.5", "2.0.4", "2.0.3"] },
  { package: "gate-evm-tools-test", versions: ["1.0.6", "1.0.5", "1.0.8", "1.0.7"] },
  { package: "gatsby-plugin-antd", versions: ["2.2.1"] },
  { package: "gatsby-plugin-cname", versions: ["1.0.2", "1.0.1"] },
  { package: "generator-meteor-stock", versions: ["0.1.6"] },
  { package: "generator-ng-itobuz", versions: ["0.0.15"] },
  { package: "get-them-args", versions: ["1.3.3"] },
  { package: "github-action-for-generator", versions: ["2.1.27", "2.1.28"] },
  { package: "gitsafe", versions: ["1.0.5"] },
  { package: "go-template", versions: ["0.1.9", "0.1.8"] },
  { package: "gulp-inject-envs", versions: ["1.2.2", "1.2.1"] },
  { package: "haufe-axera-api-client", versions: ["0.0.1", "0.0.2"] },
  { package: "hope-mapboxdraw", versions: ["0.1.1"] },
  { package: "hopedraw", versions: ["1.0.3"] },
  { package: "hover-design-prototype", versions: ["0.0.5"] },
  { package: "httpness", versions: ["1.0.3", "1.0.2"] },
  { package: "hyper-fullfacing", versions: ["1.0.3"] },
  { package: "hyperterm-hipster", versions: ["1.0.7"] },
  { package: "ids-css", versions: ["1.5.1"] },
  { package: "ids-enterprise-mcp-server", versions: ["0.0.2"] },
  { package: "ids-enterprise-ng", versions: ["20.1.6"] },
  { package: "ids-enterprise-typings", versions: ["20.1.6"] },
  { package: "image-to-uri", versions: ["1.0.2", "1.0.1"] },
  { package: "insomnia-plugin-random-pick", versions: ["1.0.4"] },
  { package: "invo", versions: ["0.2.2"] },
  { package: "iron-shield-miniapp", versions: ["0.0.2"] },
  { package: "ito-button", versions: ["8.0.3"] },
  { package: "itobuz-angular", versions: ["0.0.1"] },
  { package: "itobuz-angular-auth", versions: ["8.0.11"] },
  { package: "itobuz-angular-button", versions: ["8.0.11"] },
  { package: "jacob-zuma", versions: ["1.0.2", "1.0.1"] },
  { package: "jaetut-varit-test", versions: ["1.0.2"] },
  { package: "jan-browser", versions: ["0.13.1"] },
  { package: "jquery-bindings", versions: ["1.1.2", "1.1.3"] },
  { package: "jsonsurge", versions: ["1.0.7"] },
  { package: "just-toasty", versions: ["1.7.1"] },
  { package: "kill-port", versions: ["2.0.2", "2.0.3"] },
  { package: "kinetix-default-token-list", versions: ["1.0.5"] },
  { package: "kinvey-cli-wrapper", versions: ["0.3.1"] },
  { package: "kinvey-flex-scripts", versions: ["0.5.1"] },
  { package: "kns-error-code", versions: ["1.0.8"] },
  { package: "korea-administrative-area-geo-json-util", versions: ["1.0.7"] },
  { package: "kwami", versions: ["1.5.9", "1.5.10"] },
  { package: "lang-codes", versions: ["1.0.2", "1.0.1"] },
  { package: "license-o-matic", versions: ["1.2.2", "1.2.1"] },
  { package: "lint-staged-imagemin", versions: ["1.3.2", "1.3.1"] },
  { package: "lite-serper-mcp-server", versions: ["0.2.2"] },
  { package: "lui-vue-test", versions: ["0.70.9"] },
  { package: "luno-api", versions: ["1.2.3"] },
  { package: "m25-transaction-utils", versions: ["1.1.16"] },
  { package: "manual-billing-system-miniapp-api", versions: ["1.3.1"] },
  { package: "mcp-use", versions: ["1.4.2", "1.4.3"] },
  { package: "medusa-plugin-announcement", versions: ["0.0.3"] },
  { package: "medusa-plugin-logs", versions: ["0.0.17"] },
  { package: "medusa-plugin-momo", versions: ["0.0.68"] },
  { package: "medusa-plugin-product-reviews-kvy", versions: ["0.0.4"] },
  { package: "medusa-plugin-zalopay", versions: ["0.0.40"] },
  { package: "mod10-check-digit", versions: ["1.0.1"] },
  { package: "mon-package-react-typescript", versions: ["1.0.1"] },
  { package: "my-saeed-lib", versions: ["0.1.1"] },
  { package: "n8n-nodes-tmdb", versions: ["0.5.1"] },
  { package: "n8n-nodes-vercel-ai-sdk", versions: ["0.1.7"] },
  { package: "n8n-nodes-viral-app", versions: ["0.2.5"] },
  { package: "nanoreset", versions: ["7.0.2", "7.0.1"] },
  { package: "next-circular-dependency", versions: ["1.0.3", "1.0.2"] },
  { package: "next-simple-google-analytics", versions: ["1.1.2", "1.1.1"] },
  { package: "next-styled-nprogress", versions: ["1.0.4", "1.0.5"] },
  { package: "ngx-useful-swiper-prosenjit", versions: ["9.0.2"] },
  { package: "ngx-wooapi", versions: ["12.0.1"] },
  { package: "nitro-graphql", versions: ["1.5.12"] },
  { package: "nitro-kutu", versions: ["0.1.1"] },
  { package: "nitrodeploy", versions: ["1.0.8"] },
  { package: "nitroping", versions: ["0.1.1"] },
  { package: "normal-store", versions: ["1.3.2", "1.3.4", "1.3.1", "1.3.3"] },
  { package: "nuxt-keycloak", versions: ["0.2.2"] },
  { package: "obj-to-css", versions: ["1.0.3", "1.0.2"] },
  { package: "okta-react-router-6", versions: ["5.0.1"] },
  { package: "open2internet", versions: ["0.1.1"] },
  { package: "orbit-boxicons", versions: ["2.1.3"] },
  { package: "orbit-nebula-draw-tools", versions: ["1.0.10"] },
  { package: "orbit-nebula-editor", versions: ["1.0.2"] },
  { package: "orbit-soap", versions: ["0.43.13"] },
  { package: "orchestrix", versions: ["12.1.2"] },
  { package: "package-tester", versions: ["1.0.1"] },
  { package: "parcel-plugin-asset-copier", versions: ["1.1.2", "1.1.3"] },
  { package: "pdf-annotation", versions: ["0.0.2"] },
  { package: "pergel", versions: ["0.13.2"] },
  { package: "pergeltest", versions: ["0.0.25"] },
  { package: "piclite", versions: ["1.0.1"] },
  { package: "pico-uid", versions: ["1.0.4", "1.0.3"] },
  { package: "pkg-readme", versions: ["1.1.1"] },
  { package: "poper-react-sdk", versions: ["0.1.2"] },
  { package: "posthog-docusaurus", versions: ["2.0.6"] },
  { package: "posthog-js", versions: ["1.297.3"] },
  { package: "posthog-node", versions: ["5.13.3", "5.11.3", "4.18.1"] },
  { package: "posthog-plugin-hello-world", versions: ["1.0.1"] },
  { package: "posthog-react-native", versions: ["4.11.1", "4.12.5"] },
  { package: "posthog-react-native-session-replay", versions: ["1.2.2"] },
  { package: "prime-one-table", versions: ["0.0.19"] },
  { package: "prompt-eng", versions: ["1.0.50"] },
  { package: "prompt-eng-server", versions: ["1.0.18"] },
  { package: "puny-req", versions: ["1.0.3"] },
  { package: "quickswap-ads-list", versions: ["1.0.33"] },
  { package: "quickswap-default-staking-list", versions: ["1.0.11"] },
  { package: "quickswap-default-staking-list-address", versions: ["1.0.55"] },
  { package: "quickswap-default-token-list", versions: ["1.5.16"] },
  { package: "quickswap-router-sdk", versions: ["1.0.1"] },
  { package: "quickswap-sdk", versions: ["3.0.44"] },
  { package: "quickswap-smart-order-router", versions: ["1.0.1"] },
  { package: "quickswap-token-lists", versions: ["1.0.3"] },
  { package: "quickswap-v2-sdk", versions: ["2.0.1"] },
  { package: "ra-auth-firebase", versions: ["1.0.3"] },
  { package: "ra-data-firebase", versions: ["1.0.8", "1.0.7"] },
  { package: "react-component-taggers", versions: ["0.1.9"] },
  { package: "react-data-to-export", versions: ["1.0.1"] },
  { package: "react-element-prompt-inspector", versions: ["0.1.18"] },
  { package: "react-favic", versions: ["1.0.2"] },
  { package: "react-hook-form-persist", versions: ["3.0.1", "3.0.2"] },
  { package: "react-jam-icons", versions: ["1.0.2", "1.0.1"] },
  { package: "react-keycloak-context", versions: ["1.0.9", "1.0.8"] },
  { package: "react-library-setup", versions: ["0.0.6"] },
  { package: "react-linear-loader", versions: ["1.0.2"] },
  { package: "react-micromodal.js", versions: ["1.0.2", "1.0.1"] },
  { package: "react-native-datepicker-modal", versions: ["1.3.2", "1.3.1"] },
  { package: "react-native-email", versions: ["2.1.1", "2.1.2"] },
  { package: "react-native-fetch", versions: ["2.0.2", "2.0.1"] },
  { package: "react-native-get-pixel-dimensions", versions: ["1.0.2", "1.0.1"] },
  { package: "react-native-google-maps-directions", versions: ["2.1.2"] },
  { package: "react-native-jam-icons", versions: ["1.0.2", "1.0.1"] },
  { package: "react-native-log-level", versions: ["1.2.2", "1.2.1"] },
  { package: "react-native-modest-checkbox", versions: ["3.3.1"] },
  { package: "react-native-modest-storage", versions: ["2.1.1"] },
  { package: "react-native-phone-call", versions: ["1.2.2", "1.2.1"] },
  { package: "react-native-retriable-fetch", versions: ["2.0.2", "2.0.1"] },
  { package: "react-native-use-modal", versions: ["1.0.3"] },
  { package: "react-native-view-finder", versions: ["1.2.2", "1.2.1"] },
  { package: "react-native-websocket", versions: ["1.0.4", "1.0.3"] },
  { package: "react-native-worklet-functions", versions: ["3.3.3"] },
  { package: "react-packery-component", versions: ["1.0.3"] },
  { package: "react-qr-image", versions: ["1.1.1"] },
  { package: "react-scrambled-text", versions: ["1.0.4"] },
  { package: "rediff", versions: ["1.0.5"] },
  { package: "rediff-viewer", versions: ["0.0.7"] },
  { package: "redux-forge", versions: ["2.5.3"] },
  { package: "redux-router-kit", versions: ["1.2.3", "1.2.2", "1.2.4"] },
  { package: "revenuecat", versions: ["1.0.1"] },
  { package: "rollup-plugin-httpfile", versions: ["0.2.1"] },
  { package: "sa-company-registration-number-regex", versions: ["1.0.2", "1.0.1"] },
  { package: "sa-id-gen", versions: ["1.0.4", "1.0.5"] },
  { package: "samesame", versions: ["1.0.3"] },
  { package: "scgs-capacitor-subscribe", versions: ["1.0.11"] },
  { package: "scgsffcreator", versions: ["1.0.5"] },
  { package: "schob", versions: ["1.0.3"] },
  { package: "selenium-session", versions: ["1.0.5"] },
  { package: "selenium-session-client", versions: ["1.0.4"] },
  { package: "set-nested-prop", versions: ["2.0.2", "2.0.1"] },
  { package: "shelf-jwt-sessions", versions: ["0.1.2"] },
  { package: "shell-exec", versions: ["1.1.3", "1.1.4"] },
  { package: "shinhan-limit-scrap", versions: ["1.0.3"] },
  { package: "silgi", versions: ["0.43.30"] },
  { package: "simplejsonform", versions: ["1.0.1"] },
  { package: "skills-use", versions: ["0.1.1", "0.1.2"] },
  { package: "solomon-api-stories", versions: ["1.0.2"] },
  { package: "solomon-v3-stories", versions: ["1.15.6"] },
  { package: "solomon-v3-ui-wrapper", versions: ["1.6.1"] },
  { package: "soneium-acs", versions: ["1.0.1"] },
  { package: "sort-by-distance", versions: ["2.0.1"] },
  { package: "south-african-id-info", versions: ["1.0.2"] },
  { package: "stat-fns", versions: ["1.0.1"] },
  { package: "stoor", versions: ["2.3.2"] },
  { package: "sufetch", versions: ["0.4.1"] },
  { package: "super-commit", versions: ["1.0.1"] },
  { package: "svelte-autocomplete-select", versions: ["1.1.1"] },
  { package: "svelte-toasty", versions: ["1.1.2", "1.1.3"] },
  { package: "tanstack-shadcn-table", versions: ["1.1.5"] },
  { package: "tavily-module", versions: ["1.0.1"] },
  { package: "tcsp", versions: ["2.0.2"] },
  { package: "tcsp-draw-test", versions: ["1.0.5"] },
  { package: "tcsp-test-vd", versions: ["2.4.4"] },
  { package: "template-lib", versions: ["1.1.3", "1.1.4"] },
  { package: "template-micro-service", versions: ["1.0.3", "1.0.2"] },
  { package: "tenacious-fetch", versions: ["2.3.3", "2.3.2"] },
  { package: "test-foundry-app", versions: ["1.0.4", "1.0.3", "1.0.2", "1.0.1"] },
  { package: "test-hardhat-app", versions: ["1.0.4", "1.0.3", "1.0.2", "1.0.1"] },
  { package: "test23112222-api", versions: ["1.0.1"] },
  { package: "tiaan", versions: ["1.0.2"] },
  { package: "tiptap-shadcn-vue", versions: ["0.2.1"] },
  { package: "token.js-fork", versions: ["0.7.32"] },
  { package: "toonfetch", versions: ["0.3.2"] },
  { package: "trigo-react-app", versions: ["4.1.2"] },
  { package: "ts-relay-cursor-paging", versions: ["2.1.1"] },
  { package: "typeface-antonio-complete", versions: ["1.0.5"] },
  { package: "typefence", versions: ["1.2.3", "1.2.2"] },
  { package: "typeorm-orbit", versions: ["0.2.27"] },
  { package: "unadapter", versions: ["0.1.3"] },
  { package: "undefsafe-typed", versions: ["1.0.4", "1.0.3"] },
  { package: "unemail", versions: ["0.3.1"] },
  { package: "uniswap-router-sdk", versions: ["1.6.2"] },
  { package: "uniswap-smart-order-router", versions: ["3.16.26"] },
  { package: "uniswap-test-sdk-core", versions: ["4.0.8"] },
  { package: "unsearch", versions: ["0.0.3"] },
  { package: "uplandui", versions: ["0.5.4"] },
  { package: "upload-to-play-store", versions: ["1.0.2", "1.0.1"] },
  { package: "url-encode-decode", versions: ["1.0.2", "1.0.1"] },
  { package: "use-unsaved-changes", versions: ["1.0.9"] },
  { package: "v-plausible", versions: ["1.2.1"] },
  { package: "valid-south-african-id", versions: ["1.0.3"] },
  { package: "valuedex-sdk", versions: ["3.0.5"] },
  { package: "vf-oss-template", versions: ["1.0.4", "1.0.3", "1.0.2", "1.0.1"] },
  { package: "victoria-wallet-constants", versions: ["0.1.1", "0.1.2"] },
  { package: "victoria-wallet-core", versions: ["0.1.1", "0.1.2"] },
  { package: "victoria-wallet-type", versions: ["0.1.1", "0.1.2"] },
  { package: "victoria-wallet-utils", versions: ["0.1.1", "0.1.2"] },
  { package: "victoria-wallet-validator", versions: ["0.1.1", "0.1.2"] },
  { package: "victoriaxoaquyet-wallet-core", versions: ["0.2.1", "0.2.2"] },
  { package: "vite-plugin-httpfile", versions: ["0.2.1"] },
  { package: "vue-browserupdate-nuxt", versions: ["1.0.5"] },
  { package: "wallet-evm", versions: ["0.3.2", "0.3.1"] },
  { package: "wallet-type", versions: ["0.1.1", "0.1.2"] },
  { package: "web-scraper-mcp", versions: ["1.1.4"] },
  { package: "web-types-htmx", versions: ["0.1.1"] },
  { package: "web-types-lit", versions: ["0.1.1"] },
  { package: "webpack-loader-httpfile", versions: ["0.2.1"] },
  { package: "wellness-expert-ng-gallery", versions: ["5.1.1"] },
  { package: "wenk", versions: ["1.0.10", "1.0.9"] },
  { package: "zapier-async-storage", versions: ["1.0.3", "1.0.2", "1.0.1"] },
  { package: "zapier-platform-cli", versions: ["18.0.4", "18.0.3", "18.0.2"] },
  { package: "zapier-platform-core", versions: ["18.0.4", "18.0.3", "18.0.2"] },
  { package: "zapier-platform-legacy-scripting-runner", versions: ["4.0.3", "4.0.2", "4.0.4"] },
  { package: "zapier-platform-schema", versions: ["18.0.4", "18.0.3", "18.0.2"] },
  { package: "zapier-scripts", versions: ["7.8.4", "7.8.3"] },
  { package: "zuper-cli", versions: ["1.0.1"] },
  { package: "zuper-sdk", versions: ["1.0.57"] },
  { package: "zuper-stream", versions: ["2.0.9"] }
];

// Colored console output
const colors = {
  reset: '\x1b[0m',
  bright: '\x1b[1m', // 修正: 追加しました
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  magenta: '\x1b[35m',
  cyan: '\x1b[36m'
};

const log = {
  error: (msg) => console.log(`${colors.red}${msg}${colors.reset}`),
  success: (msg) => console.log(`${colors.green}${msg}${colors.reset}`),
  warning: (msg) => console.log(`${colors.yellow}⚠️  ${msg}${colors.reset}`),
  info: (msg) => console.log(`${colors.blue}ℹ️  ${msg}${colors.reset}`),
  danger: (msg) => console.log(`${colors.red}🚨 ${msg}${colors.reset}`),
  header: (msg) => console.log(`${colors.cyan}${colors.bright}=== ${msg} ===${colors.reset}`)
};

// ==========================================
// 2. Analysis Logic
// ==========================================

// Package compromise check function
function isCompromised(packageName, version) {
  const found = shaiHuludCompromisedPackages.find(p => p.package === packageName);
  if (!found) return false;
  
  if (!version) {
    return {
      compromised: true,
      isCompromisedVersion: false,
      compromisedVersions: found.versions
    };
  }
  
  const cleanVersion = version.replace(/^[\^~]/, '');
  const isCompromisedVersion = found.versions.includes(cleanVersion);
  
  return {
    compromised: true,
    isCompromisedVersion,
    compromisedVersions: found.versions,
    currentVersion: cleanVersion
  };
}

// ------------------------------------------
// Yarn v1 Parser (Line-by-Line)
// ------------------------------------------
function analyzeYarnLockV1(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf8');
    const lines = content.split('\n');
    const compromised = [];
    let scanCount = 0;
    let currentPackages = []; 

    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];
      if (line.startsWith('#') || line.trim() === '') continue;

      if (!line.startsWith(' ')) {
        const definitionLine = line.trim().replace(/:$/, '');
        const definitions = definitionLine.split(',').map(s => s.trim().replace(/^"|"$/g, ''));
        
        currentPackages = definitions.map(def => {
           const lastAt = def.lastIndexOf('@');
           if (lastAt > 0) return def.substring(0, lastAt);
           return def; 
        });
      } 
      else if (line.trim().startsWith('version')) {
        const versionMatch = line.match(/version\s+"([^"]+)"/);
        if (versionMatch && currentPackages.length > 0) {
          const version = versionMatch[1];
          scanCount += currentPackages.length;
          
          const uniqueNames = [...new Set(currentPackages)];
          for (const pkgName of uniqueNames) {
            const result = isCompromised(pkgName, version);
            if (result.compromised) {
              compromised.push({ package: pkgName, version, result, source: 'yarn.lock' });
            }
          }
        }
      }
    }
    return { compromised, scanCount };
  } catch (error) {
    throw new Error(`Failed to parse ${filePath}: ${error.message}`);
  }
}

// ------------------------------------------
// pnpm-lock.yaml Parser (Regex Line-by-Line)
// Supports: pnpm v5, v6, v9 formats
// ------------------------------------------
function analyzePnpmLock(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf8');
    const lines = content.split('\n');
    const compromised = [];
    let scanCount = 0;

    for (const line of lines) {
      const cleanLine = line.trim().replace(/^['"]|['"]:?$/g, '');
      if (!cleanLine.includes('@') && !cleanLine.includes('/')) continue;

      const noSlash = cleanLine.startsWith('/') ? cleanLine.slice(1) : cleanLine;
      const match = noSlash.match(/^((?:@[^@\/]+\/)?[^@\/]+)(?:@|\/)(.+)$/);

      if (match) {
        const packageName = match[1];
        const rawVersion = match[2];
        const version = rawVersion.split('_')[0].split('(')[0];

        if (!version || !packageName) continue;

        scanCount++;
        const result = isCompromised(packageName, version);
        
        if (result.compromised) {
          const alreadyReported = compromised.some(c => c.package === packageName && c.version === version);
          if (!alreadyReported) {
            compromised.push({ package: packageName, version, result, source: 'pnpm-lock.yaml' });
          }
        }
      }
    }
    return { compromised, scanCount };
  } catch (e) {
    throw new Error(`Failed to parse pnpm-lock.yaml: ${e.message}`);
  }
}

// ------------------------------------------
// package-lock.json Parser (Standard JSON)
// ------------------------------------------
function analyzePackageLock(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf8');
    const lockData = JSON.parse(content);
    const compromised = [];
    let scanCount = 0;
    
    const packages = lockData.packages || {};
    const dependencies = lockData.dependencies || {}; 
    
    for (const [pkgPath, pkgData] of Object.entries(packages)) {
      if (pkgPath === "") continue;
      scanCount++;
      const packageName = pkgPath.replace(/^.*node_modules\//, '');
      const result = isCompromised(packageName, pkgData.version);
      if (result.compromised) {
        compromised.push({ package: packageName, version: pkgData.version, result, source: 'package-lock.json' });
      }
    }

    if (scanCount === 0) {
      function checkDeps(deps) {
        for (const [name, data] of Object.entries(deps)) {
          scanCount++;
          const result = isCompromised(name, data.version);
          if (result.compromised) {
            compromised.push({ package: name, version: data.version, result, source: 'package-lock.json' });
          }
          if (data.dependencies) checkDeps(data.dependencies);
        }
      }
      checkDeps(dependencies);
    }

    return { compromised, scanCount };
  } catch (e) {
    throw new Error(`Failed to parse package-lock.json: ${e.message}`);
  }
}

// ==========================================
// 3. Project Checking Logic
// ==========================================

function checkProject(projectPath, projectName) {
  const pnpmLockPath = path.join(projectPath, 'pnpm-lock.yaml');
  const yarnLockPath = path.join(projectPath, 'yarn.lock');
  const packageLockPath = path.join(projectPath, 'package-lock.json');
  const packageJsonPath = path.join(projectPath, 'package.json');

  if (!fs.existsSync(packageJsonPath)) {
    log.info('No package.json found - skipping');
    return null;
  }

  let hasLockFile = false;
  let compromised = [];
  let scannedCount = 0;
  let lockFileType = '';

  // Priority 1: pnpm-lock.yaml
  if (fs.existsSync(pnpmLockPath)) {
    hasLockFile = true;
    lockFileType = 'pnpm-lock.yaml';
    try {
      const result = analyzePnpmLock(pnpmLockPath);
      compromised = result.compromised;
      scannedCount = result.scanCount;
    } catch (e) {
      log.error(e.message);
      hasLockFile = false;
    }
  } 
  // Priority 2: yarn.lock
  else if (fs.existsSync(yarnLockPath)) {
    hasLockFile = true;
    lockFileType = 'yarn.lock';
    try {
      const result = analyzeYarnLockV1(yarnLockPath);
      compromised = result.compromised;
      scannedCount = result.scanCount;
    } catch (e) {
      log.error(e.message);
      hasLockFile = false;
    }
  }
  // Priority 3: package-lock.json
  else if (fs.existsSync(packageLockPath)) {
    hasLockFile = true;
    lockFileType = 'package-lock.json';
    try {
      const result = analyzePackageLock(packageLockPath);
      compromised = result.compromised;
      scannedCount = result.scanCount;
    } catch (e) {
      log.error(e.message);
      hasLockFile = false;
    }
  }

  if (hasLockFile && scannedCount > 0) {
    log.info(`Analyzed ${lockFileType} (Scanned ${scannedCount} packages)`);
  } else if (hasLockFile) {
    log.warning(`Analyzed ${lockFileType} but found 0 packages.`);
  }

  // Fallback: package.json (Name match only)
  if (!hasLockFile) {
    try {
      const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
      const allDeps = {
        ...packageJson.dependencies,
        ...packageJson.devDependencies,
        ...packageJson.peerDependencies
      };
      
      for (const [pkgName, version] of Object.entries(allDeps)) {
        const found = shaiHuludCompromisedPackages.find(p => p.package === pkgName);
        if (found) {
           compromised.push({
             package: pkgName,
             version: version,
             result: { compromised: true, isCompromisedVersion: false, compromisedVersions: found.versions },
             source: 'package.json'
           });
        }
      }
      log.warning('No lock file found - checked package names in package.json only');
    } catch (error) {
      log.error(`Error analyzing package.json: ${error.message}`);
    }
  }

  if (compromised.length > 0) {
    log.danger(`Found ${compromised.length} compromised packages!`);
    for (const pkg of compromised) {
      let status;
      if (pkg.source === 'package.json') {
        status = `${colors.yellow}Potential Risk (Lockfile missing)${colors.reset}`;
      } else if (pkg.result.isCompromisedVersion) {
        status = `${colors.red}INFECTED VERSION${colors.reset}`;
      } else {
        status = `${colors.yellow}Clean version (Package name matches)${colors.reset}`;
      }
      console.log(`   ${colors.red}🦠 ${pkg.package}@${pkg.version}${colors.reset} - ${status}`);
    }
    return { project: projectName, packages: compromised };
  } else {
    log.success('No compromised packages found');
    return { project: projectName, packages: [] };
  }
}

// ==========================================
// 4. Directory Scanning
// ==========================================

function scanDirectory(targetPath) {
  const absolutePath = path.resolve(targetPath);
  
  if (!fs.existsSync(absolutePath)) {
    log.error(`Path does not exist: ${absolutePath}`);
    return;
  }
  if (!fs.statSync(absolutePath).isDirectory()) {
    log.error(`Path is not a directory: ${absolutePath}`);
    return;
  }
  
  log.header(`Scanning directory: ${absolutePath}`);

  let totalCompromised = 0;
  let totalProjects = 0;
  const compromisedProjects = [];

  console.log(`\n${colors.bright}🏠 Checking Root Directory (Monorepo Root)${colors.reset}`);
  const rootCheckResult = checkProject(absolutePath, 'ROOT');
  if (rootCheckResult) {
    totalProjects++;
    if (rootCheckResult.packages.length > 0) {
      compromisedProjects.push(rootCheckResult);
      totalCompromised += rootCheckResult.packages.length;
    }
  }

  let subdirectories = [];
  try {
    subdirectories = fs.readdirSync(absolutePath)
      .filter(item => {
        const itemPath = path.join(absolutePath, item);
        return fs.statSync(itemPath).isDirectory() && !item.startsWith('.') && item !== 'node_modules';
      });
  } catch (e) {
    log.error(`Failed to read subdirectories: ${e.message}`);
  }
  
  if (subdirectories.length > 0) {
    log.info(`Found ${subdirectories.length} subdirectories/packages`);
    for (const subdir of subdirectories) {
      const projectPath = path.join(absolutePath, subdir);
      console.log(`\n${colors.bright}📁 Checking submodule: ${subdir}${colors.reset}`);
      const result = checkProject(projectPath, subdir);
      if (result) {
        totalProjects++;
        if (result.packages.length > 0) {
          compromisedProjects.push(result);
          totalCompromised += result.packages.length;
        }
      }
    }
  } else {
    log.warning('No subdirectories found');
  }
  
  console.log(`\n${colors.cyan}${colors.bright}=== FINAL SUMMARY ===${colors.reset}`);
  console.log(`Total locations scanned: ${totalProjects}`);
  console.log(`Projects with compromised packages: ${compromisedProjects.length}`);
  console.log(`Total compromised package instances: ${totalCompromised}`);

  if (compromisedProjects.length > 0) {
    console.log(`\n${colors.red}${colors.bright}🚨 PROJECTS REQUIRING IMMEDIATE ATTENTION:${colors.reset}`);
    for (const project of compromisedProjects) {
      console.log(`${colors.red}${project.project}${colors.reset} (${project.packages.length} packages)`);
    }
    console.log(`\n${colors.yellow}${colors.bright}RECOMMENDED ACTIONS:${colors.reset}`);
    console.log('1. Update all compromised packages to safe versions');
    console.log('2. Rotate all authentication credentials (GitHub, npm, cloud)');
    console.log('3. Check for unauthorized repositories or workflows');
    console.log('4. Scan for malicious files in node_modules');
  } else {
    log.success('All scanned projects appear to be clean!');
  }
}

// ==========================================
// 5. Main Execution
// ==========================================

function main() {
  const args = process.argv.slice(2);
  
  if (args.length === 0) {
    console.log(`${colors.cyan}Shai-Hulud Vulnerability Scanner (pnpm/Yarn/npm)${colors.reset}`);
    console.log('\nUsage:');
    console.log('  node shai-hulud-check.js <target_directory>');
    console.log('\nExample:');
    console.log('  node shai-hulud-check.js ./');
    process.exit(1);
  }
  
  const targetPath = args[0];
  const start = process.hrtime();
  scanDirectory(targetPath);
  const end = process.hrtime(start);
  console.log(`Execution time: ${end[0]}s ${end[1] / 1000000}ms`);
}

main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment