#!/bin/bash
# 1. Determine the target directory (default to current directory if not provided)
TARGET_DIR="${1:-.}"
# Remove trailing slash from directory path if present
TARGET_DIR="${TARGET_DIR%/}"
# 2. Validation
if [ ! -d "$TARGET_DIR" ]; then
echo "Error: Directory '$TARGET_DIR' does not exist."
exit 1
fi
# 3. Define the list of packages to check
export TARGET_PACKAGES=$(cat <<EOF
@accordproject/concerto-analysis
@accordproject/markdown-docx
@accordproject/markdown-it-cicero
@actbase/css-to-react-native-transform
@actbase/native
@actbase/node-server
@actbase/react-absolute
@actbase/react-daum-postcode
@actbase/react-kakaosdk
@actbase/react-native-actionsheet
@actbase/react-native-devtools
@actbase/react-native-fast-image
@actbase/react-native-kakao-channel
@actbase/react-native-kakao-navi
@actbase/react-native-less-transformer
@actbase/react-native-naver-login
@actbase/react-native-simple-video
@actbase/react-native-tiktok
@alexcolls/nuxt-socket.io
@alexcolls/nuxt-ux
@aryanhussain/my-angular-lib
@asyncapi/avro-schema-parser
@asyncapi/bundler
@asyncapi/cli
@asyncapi/converter
@asyncapi/diff
@asyncapi/dotnet-rabbitmq-template
@asyncapi/edavisualiser
@asyncapi/generator
@asyncapi/generator-components
@asyncapi/generator-helpers
@asyncapi/generator-react-sdk
@asyncapi/go-watermill-template
@asyncapi/html-template
@asyncapi/java-spring-cloud-stream-template
@asyncapi/java-spring-template
@asyncapi/java-template
@asyncapi/keeper
@asyncapi/markdown-template
@asyncapi/modelina
@asyncapi/modelina-cli
@asyncapi/multi-parser
@asyncapi/nodejs-template
@asyncapi/nodejs-ws-template
@asyncapi/nunjucks-filters
@asyncapi/openapi-schema-parser
@asyncapi/optimizer
@asyncapi/parser
@asyncapi/php-template
@asyncapi/problem
@asyncapi/protobuf-schema-parser
@asyncapi/python-paho-template
@asyncapi/react-component
@asyncapi/server-api
@asyncapi/specs
@asyncapi/studio
@asyncapi/web-component
@caretive/caret-cli
@clausehq/flows-step-jsontoxml
@clausehq/flows-step-sendgridemail
@commute/bloom
@commute/market-data
@dev-blinq/ai-qa-logic
@dev-blinq/cucumber_client
@ensdomains/address-encoder
@ensdomains/blacklist
@ensdomains/buffer
@ensdomains/ccip-read-cf-worker
@ensdomains/ccip-read-dns-gateway
@ensdomains/ccip-read-router
@ensdomains/ccip-read-worker-viem
@ensdomains/content-hash
@ensdomains/curvearithmetics
@ensdomains/cypress-metamask
@ensdomains/dnsprovejs
@ensdomains/dnssec-oracle-anchors
@ensdomains/dnssecoraclejs
@ensdomains/durin
@ensdomains/durin-middleware
@ensdomains/ens-archived-contracts
@ensdomains/ens-avatar
@ensdomains/ens-contracts
@ensdomains/ensjs
@ensdomains/ensjs-react
@ensdomains/ens-test-env
@ensdomains/ens-validation
@ensdomains/eth-ens-namehash
@ensdomains/hackathon-registrar
@ensdomains/hardhat-chai-matchers-viem
@ensdomains/hardhat-toolbox-viem-extended
@ensdomains/mock
@ensdomains/name-wrapper
@ensdomains/offchain-resolver-contracts
@ensdomains/op-resolver-contracts
@ensdomains/react-ens-address
@ensdomains/renewal
@ensdomains/renewal-widget
@ensdomains/reverse-records
@ensdomains/server-analytics
@ensdomains/solsha1
@ensdomains/subdomain-registrar
@ensdomains/test-utils
@ensdomains/thorin
@ensdomains/ui
@ensdomains/unicode-confusables
@ensdomains/unruggable-gateways
@ensdomains/vite-plugin-i18next-loader
@ensdomains/web3modal
@everreal/web-analytics
@fishingbooker/browser-sync-plugin
@fishingbooker/react-swiper
@hapheus/n8n-nodes-pgp
@ifelsedeveloper/protocol-contracts-svm-idl
@ifings/design-system
@kvytech/cli
@kvytech/components
@kvytech/habbit-e2e-test
@kvytech/medusa-plugin-announcement
@kvytech/medusa-plugin-management
@kvytech/medusa-plugin-newsletter
@kvytech/medusa-plugin-product-reviews
@kvytech/medusa-plugin-promotion
@kvytech/web
@lessondesk/api-client
@lessondesk/babel-preset
@lessondesk/eslint-config
@lessondesk/schoolbus
@louisle2/core
@louisle2/cortex-js
@lpdjs/firestore-repo-service
@markvivanco/app-version-checker
@mcp-use/cli
@mcp-use/inspector
@mcp-use/mcp-use
@mparpaillon/connector-parse
@mparpaillon/imagesloaded
@orbitgtbelgium/mapbox-gl-draw-cut-polygon-mode
@orbitgtbelgium/mapbox-gl-draw-scale-rotate-mode
@orbitgtbelgium/orbit-components
@orbitgtbelgium/time-slider
@osmanekrem/error-handler
@posthog/agent
@posthog/ai
@posthog/automatic-cohorts-plugin
@posthog/bitbucket-release-tracker
@posthog/cli
@posthog/clickhouse
@posthog/core
@posthog/currency-normalization-plugin
@posthog/customerio-plugin
@posthog/databricks-plugin
@posthog/drop-events-on-property-plugin
@posthog/event-sequence-timer-plugin
@posthog/filter-out-plugin
@posthog/first-time-event-tracker
@posthog/geoip-plugin
@posthog/github-release-tracking-plugin
@posthog/gitub-star-sync-plugin
@posthog/heartbeat-plugin
@posthog/hedgehog-mode
@posthog/icons
@posthog/ingestion-alert-plugin
@posthog/intercom-plugin
@posthog/kinesis-plugin
@posthog/laudspeaker-plugin
@posthog/lemon-ui
@posthog/maxmind-plugin
@posthog/migrator3000-plugin
@posthog/netdata-event-processing
@posthog/nextjs
@posthog/nextjs-config
@posthog/nuxt
@posthog/pagerduty-plugin
@posthog/piscina
@posthog/plugin-contrib
@posthog/plugin-server
@posthog/plugin-unduplicates
@posthog/postgres-plugin
@posthog/react-rrweb-player
@posthog/rrdom
@posthog/rrweb
@posthog/rrweb-player
@posthog/rrweb-record
@posthog/rrweb-replay
@posthog/rrweb-snapshot
@posthog/rrweb-utils
@posthog/sendgrid-plugin
@posthog/siphash
@posthog/snowflake-export-plugin
@posthog/taxonomy-plugin
@posthog/twilio-plugin
@posthog/twitter-followers-plugin
@posthog/url-normalizer-plugin
@posthog/variance-plugin
@posthog/web-dev-server
@posthog/wizard
@posthog/zendesk-plugin
@postman/aether-icons
@postman/csv-parse
@postman/final-node-keytar
@postman/mcp-ui-client
@postman/node-keytar
@postman/pm-bin-linux-x64
@postman/pm-bin-macos-arm64
@postman/pm-bin-macos-x64
@postman/pm-bin-windows-x64
@postman/postman-collection-fork
@postman/postman-mcp-cli
@postman/postman-mcp-server
@postman/pretty-ms
@postman/secret-scanner-wasm
@postman/tunnel-agent
@postman/wdio-allure-reporter
@postman/wdio-junit-reporter
@quick-start-soft/quick-document-translator
@quick-start-soft/quick-git-clean-markdown
@quick-start-soft/quick-markdown
@quick-start-soft/quick-markdown-compose
@quick-start-soft/quick-markdown-image
@quick-start-soft/quick-markdown-print
@quick-start-soft/quick-markdown-translator
@quick-start-soft/quick-remove-image-background
@quick-start-soft/quick-task-refine
@seung-ju/next
@seung-ju/openapi-generator
@seung-ju/react-hooks
@seung-ju/react-native-action-sheet
@strapbuild/react-native-date-time-picker
@strapbuild/react-native-perspective-image-cropper
@strapbuild/react-native-perspective-image-cropper-2
@strapbuild/react-native-perspective-image-cropper-poojan31
@thedelta/eslint-config
@tiaanduplessis/json
@tiaanduplessis/react-progressbar
@trefox/sleekshop-js
@trigo/atrix
@trigo/atrix-acl
@trigo/atrix-elasticsearch
@trigo/atrix-mongoose
@trigo/atrix-orientdb
@trigo/atrix-postgres
@trigo/atrix-pubsub
@trigo/atrix-redis
@trigo/atrix-soap
@trigo/atrix-swagger
@trigo/bool-expressions
@trigo/eslint-config-trigo
@trigo/fsm
@trigo/hapi-auth-signedlink
@trigo/jsdt
@trigo/keycloak-api
@trigo/node-soap
@trigo/pathfinder-ui-css
@trigo/trigo-hapijs
@varsityvibe/api-client
@varsityvibe/validation-schemas
@zapier/ai-actions
@zapier/ai-actions-react
@zapier/babel-preset-zapier
@zapier/browserslist-config-zapier
@zapier/eslint-plugin-zapier
@zapier/mcp-integration
@zapier/secret-scrubber
@zapier/spectral-api-ruleset
@zapier/stubtree
@zapier/zapier-sdk
asyncapi-preview
atrix
atrix-mongoose
axios-builder
axios-cancelable
axios-timed
barebones-css
blinqio-executions-cli
bool-expressions
bun-plugin-httpfile
bytecode-checker-cli
bytes-to-x
calc-loan-interest
capacitor-plugin-apptrackingios
capacitor-plugin-purchase
capacitor-plugin-scgssigninwithgoogle
capacitor-purchase-history
capacitor-voice-recorder-wav
chrome-extension-downloads
claude-token-updater
coinmarketcap-api
command-irail
compare-obj
count-it-down
cpu-instructions
create-glee-app
create-hardhat3-app
create-mcp-use-app
crypto-addr-codec
designstudiouiux
devstart-cli
discord-bot-server
dotnet-template
drop-events-on-property-plugin
enforce-branch-name
eslint-config-trigo
eslint-config-zeallat-base
ethereum-ens
evm-checkcode-cli
exact-ticker
expo-audio-session
feature-flip
fittxt
flapstacks
flatten-unflatten
formik-error-focus
formik-store
fuzzy-finder
gate-evm-check-code2
gate-evm-tools-test
gatsby-plugin-cname
get-them-args
github-action-for-generator
gitsafe
go-template
haufe-axera-api-client
hopedraw
hope-mapboxdraw
hyperterm-hipster
image-to-uri
invo
iron-shield-miniapp
ito-button
itobuz-angular
itobuz-angular-auth
jacob-zuma
jan-browser
jquery-bindings
just-toasty
kill-port
korea-administrative-area-geo-json-util
license-o-matic
lint-staged-imagemin
lite-serper-mcp-server
luno-api
manual-billing-system-miniapp-api
mcp-use
medusa-plugin-announcement
medusa-plugin-logs
medusa-plugin-momo
medusa-plugin-product-reviews-kvy
medusa-plugin-zalopay
mon-package-react-typescript
n8n-nodes-tmdb
nanoreset
next-circular-dependency
obj-to-css
okta-react-router-6
open2internet
orbit-boxicons
orbit-nebula-draw-tools
orbit-nebula-editor
orbit-soap
parcel-plugin-asset-copier
piclite
pico-uid
poper-react-sdk
posthog-docusaurus
posthog-js
posthog-node
posthog-plugin-hello-world
posthog-react-native
posthog-react-native-session-replay
ra-data-firebase
react-component-taggers
react-element-prompt-inspector
react-jam-icons
react-keycloak-context
react-library-setup
react-native-datepicker-modal
react-native-email
react-native-fetch
react-native-get-pixel-dimensions
react-native-jam-icons
react-native-log-level
react-native-phone-call
react-native-retriable-fetch
react-native-use-modal
react-native-view-finder
react-native-websocket
react-native-worklet-functions
react-qr-image
redux-forge
redux-router-kit
sa-company-registration-number-regex
sa-id-gen
scgs-capacitor-subscribe
scgsffcreator
set-nested-prop
shell-exec
shinhan-limit-scrap
skills-use
sort-by-distance
stoor
svelte-autocomplete-select
tcsp-draw-test
tenacious-fetch
test23112222-api
test-foundry-app
test-hardhat-app
token.js-fork
trigo-react-app
typeorm-orbit
undefsafe-typed
uplandui
url-encode-decode
vite-plugin-httpfile
web-types-htmx
web-types-lit
wenk
zapier-async-storage
zapier-platform-cli
zapier-platform-core
zapier-platform-legacy-scripting-runner
zapier-platform-schema
zapier-scripts
zuper-cli
zuper-sdk
zuper-stream
EOF
)
# 4. Search for package.json files (INCLUDING node_modules)
echo "Searching for package.json files in '$TARGET_DIR'..."
echo "INCLUDING 'node_modules' directories (This will be verbose)."
echo "-----------------------------------------------"
# Use find to locate files, pipe to while loop
find "$TARGET_DIR" -type f -name "package.json" | while read -r PACKAGE_JSON_PATH; do
# Export the current path for the Node script
export PACKAGE_JSON_PATH
# Execute Node.js logic
# We suppress raw node output unless we explicitly console.log
node -e '
const fs = require("fs");
const targetList = process.env.TARGET_PACKAGES.trim().split(/\s+/);
const pkgPath = process.env.PACKAGE_JSON_PATH;
try {
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
const installed = {
...(pkg.dependencies || {}),
...(pkg.devDependencies || {}),
...(pkg.peerDependencies || {})
};
const installedKeys = Object.keys(installed);
const found = targetList.filter(target => installedKeys.includes(target));
if (found.length > 0) {
found.forEach(f => {
console.log(`\x1b[31m[DANGER FOUND]\x1b[0m ${pkgPath} -> ${f}`);
});
} else {
console.log(`\x1b[32m[OK] Clean\x1b[0m ${pkgPath}`);
}
} catch (err) {
console.error(`\x1b[33m[ERROR]\x1b[0m Could not parse ${pkgPath}`);
}
'
done
echo "-----------------------------------------------"
echo "Deep Scan Complete."
Put it in a file named -> detect-shai-hulud-package.sh
Then add it inside your mendix project directory
Open a git terminal and run ./detect-shai-hulud-package.sh