Skip to content

Instantly share code, notes, and snippets.

@ruivieira
Last active November 26, 2025 19:21
Show Gist options
  • Select an option

  • Save ruivieira/f80c35e83eebe09e61011cc14ba53710 to your computer and use it in GitHub Desktop.

Select an option

Save ruivieira/f80c35e83eebe09e61011cc14ba53710 to your computer and use it in GitHub Desktop.
Script to check Shai-Hulud packages (LIST NOT COMPREHENSIVE)
#!/usr/bin/env bash
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
DUNE_SEARCH_MESSAGES=(
"He who controls the lockfiles controls the universe…"
"Walking without rhythm so we don’t attract Shai-Hulud… yet."
"Muad'Dib audits the dependencies. You should, too."
"Casting the gom jabbar of grep onto your lockfiles."
"Searching the desert of packages for signs of corruption."
"The spice extends life. These dependencies? Unclear."
)
DUNE_HIT_MESSAGES=(
"Shai-Hulud has surfaced — a worm of dependency has been found."
"You tried to walk without rhythm, but the worm still came."
"The spice must flow, but these packages should probably go."
"The Fremen would not tolerate such weak packages."
"I must not fear. I will audit. I will remove."
)
rand_msg() {
local -n arr=$1
local size=${#arr[@]}
if [ "$size" -eq 0 ]; then
return
fi
local idx=$(( RANDOM % size ))
echo "${arr[$idx]}"
}
ROOT_DIR="${1:-.}"
AFFECTED_PACKAGES=(
"@actbase/css-to-react-native-transform"
"@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"
"@alaan/s2s-auth"
"@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/web-component"
"@caretive/caret-cli"
"@ensdomains/address-encoder"
"@ensdomains/blacklist"
"@ensdomains/buffer"
"@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-middleware"
"@ensdomains/ens-archived-contracts"
"@ensdomains/ens-avatar"
"@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/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"
"@kvytech/cli"
"@kvytech/components"
"@kvytech/medusa-plugin-announcement"
"@kvytech/medusa-plugin-management"
"@kvytech/medusa-plugin-newsletter"
"@kvytech/medusa-plugin-product-reviews"
"@kvytech/web"
"@louisle2/cortex-js"
"@markvivanco/app-version-checker"
"@mcp-use/cli"
"@mcp-use/inspector"
"@mcp-use/mcp-use"
"@mparpaillon/connector-parse"
"@mparpaillon/imagesloaded"
"@mparpaillon/page"
"@orbitgtbelgium/mapbox-gl-draw-scale-rotate-mode"
"@orbitgtbelgium/orbit-components"
"@orbitgtbelgium/time-slider"
"@posthog/agent"
"@posthog/ai"
"@posthog/automatic-cohorts-plugin"
"@posthog/cli"
"@posthog/core"
"@posthog/currency-normalization-plugin"
"@posthog/customerio-plugin"
"@posthog/databricks-plugin"
"@posthog/event-sequence-timer-plugin"
"@posthog/first-time-event-tracker"
"@posthog/geoip-plugin"
"@posthog/github-release-tracking-plugin"
"@posthog/gitub-star-sync-plugin"
"@posthog/hedgehog-mode"
"@posthog/ingestion-alert-plugin"
"@posthog/kinesis-plugin"
"@posthog/maxmind-plugin"
"@posthog/nextjs"
"@posthog/nextjs-config"
"@posthog/nuxt"
"@posthog/pagerduty-plugin"
"@posthog/piscina"
"@posthog/plugin-contrib"
"@posthog/plugin-unduplicates"
"@posthog/react-rrweb-player"
"@posthog/rrdom"
"@posthog/rrweb"
"@posthog/rrweb-player"
"@posthog/rrweb-record"
"@posthog/rrweb-snapshot"
"@posthog/rrweb-utils"
"@posthog/sendgrid-plugin"
"@posthog/siphash"
"@posthog/snowflake-export-plugin"
"@posthog/taxonomy-plugin"
"@posthog/twitter-followers-plugin"
"@posthog/twilio-plugin"
"@posthog/url-normalizer-plugin"
"@posthog/variance-plugin"
"@posthog/web-dev-server"
"@posthog/wizard"
"@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-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"
"@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/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"
"@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"
"bool-expressions"
"bytecode-checker-cli"
"calc-loan-interest"
"capacitor-plugin-apptrackingios"
"capacitor-plugin-purchase"
"capacitor-plugin-scgssigninwithgoogle"
"capacitor-purchase-history"
"capacitor-voice-recorder-wav"
"claude-token-updater"
"cpu-instructions"
"create-glee-app"
"create-hardhat3-app"
"create-mcp-use-app"
"crypto-addr-codec"
"devstart-cli"
"discord-bot-server"
"dotnet-template"
"esbuild-plugin-eta"
"esbuild-plugin-httpfile"
"eslint-config-trigo"
"eslint-config-zeallat-base"
"ethereum-ens"
"evm-checkcode-cli"
"exact-ticker"
"expo-audio-session"
"gate-evm-check-code2"
"gate-evm-tools-test"
"github-action-for-generator"
"go-template"
"iron-shield-miniapp"
"jan-browser"
"korea-administrative-area-geo-json-util"
"lite-serper-mcp-server"
"manual-billing-system-miniapp-api"
"mcp-use"
"medusa-plugin-announcement"
"medusa-plugin-momo"
"medusa-plugin-product-reviews-kvy"
"medusa-plugin-zalopay"
"n8n-nodes-tmdb"
"open2internet"
"orbit-boxicons"
"orbit-nebula-draw-tools"
"orbit-nebula-editor"
"orbit-soap"
"poper-react-sdk"
"posthog-docusaurus"
"posthog-node"
"posthog-plugin-hello-world"
"posthog-react-native"
"posthog-react-native-session-replay"
"react-element-prompt-inspector"
"react-library-setup"
"react-native-use-modal"
"react-native-worklet-functions"
"redux-forge"
"redux-router-kit"
"rollup-plugin-httpfile"
"scgs-capacitor-subscribe"
"scgsffcreator"
"shinhan-limit-scrap"
"skills-use"
"test-foundry-app"
"test-hardhat-app"
"token.js-fork"
"trigo-react-app"
"typeorm-orbit"
"vite-plugin-httpfile"
"web-types-lit"
"zapier-async-storage"
"zapier-platform-cli"
"zapier-platform-core"
"zapier-platform-legacy-scripting-runner"
"zapier-platform-schema"
"zapier-scripts"
"zuper-cli"
"zuper-stream"
)
echo "=================================================="
echo " Affected NPM Packages Security Checker"
echo "=================================================="
echo ""
echo -e "Scanning under: ${CYAN}${ROOT_DIR}${NC}"
echo "Checking ${#AFFECTED_PACKAGES[@]} potentially vulnerable packages..."
echo ""
echo -e "${YELLOW}$(rand_msg DUNE_SEARCH_MESSAGES)${NC}"
echo ""
echo "Searching for dependency files (yarn.lock, package-lock.json, pnpm-lock.yaml, pnpm-lock.yml, deno.lock, package.json)..."
echo ""
DEP_FILES=()
GLOBAL_FOUND_PACKAGES=()
PROJECTS_WITH_HITS=0
while IFS= read -r -d '' file; do
DEP_FILES+=("$file")
done < <(find "$ROOT_DIR" -type f \
\( -name 'yarn.lock' -o -name 'package-lock.json' -o -name 'pnpm-lock.yaml' -o -name 'pnpm-lock.yml' -o -name 'deno.lock' -o -name 'package.json' \) \
-print0)
if [ "${#DEP_FILES[@]}" -eq 0 ]; then
echo -e "${YELLOW}No dependency files found under ${ROOT_DIR}.${NC}"
echo -e "${YELLOW}The desert is quiet. No worms today.${NC}"
exit 0
fi
for dep_file in "${DEP_FILES[@]}"; do
echo "--------------------------------------------------"
echo -e "Scanning file: ${CYAN}${dep_file}${NC}"
echo -e "${YELLOW}$(rand_msg DUNE_SEARCH_MESSAGES)${NC}"
found_count=0
found_packages=()
for package in "${AFFECTED_PACKAGES[@]}"; do
if grep -qF "\"${package}@" "$dep_file" 2>/dev/null || \
grep -qF "\"${package}\"" "$dep_file" 2>/dev/null || \
grep -qF "${package}\":" "$dep_file" 2>/dev/null; then
found_packages+=("$package")
GLOBAL_FOUND_PACKAGES+=("$package")
((found_count++))
fi
done
if [ "$found_count" -eq 0 ]; then
echo -e "${GREEN}✓ CLEAN - No affected packages found in this file.${NC}"
echo -e "${GREEN}The sand shifts, but no worm answers.${NC}"
else
((PROJECTS_WITH_HITS++))
echo -e "${RED}⚠ WARNING - Found ${found_count} affected package(s) in this file:${NC}"
echo ""
for pkg in "${found_packages[@]}"; do
echo -e " ${RED}✗${NC} $pkg"
done
echo ""
msgs_to_print=$(( found_count ))
if [ "$msgs_to_print" -gt 3 ]; then
msgs_to_print=3
fi
for ((i=0; i<msgs_to_print; i++)); do
echo -e "${RED}$(rand_msg DUNE_HIT_MESSAGES)${NC}"
done
fi
echo ""
done
echo "=================================================="
echo " SUMMARY"
echo "=================================================="
echo "Total dependency files scanned: ${#DEP_FILES[@]}"
echo "Files with hits: $PROJECTS_WITH_HITS"
if [ "${#GLOBAL_FOUND_PACKAGES[@]}" -eq 0 ]; then
echo -e "${GREEN}✓ CLEAN - No affected packages found in any scanned file.${NC}"
echo ""
echo "Your projects do not appear to use any of the ${#AFFECTED_PACKAGES[@]} affected packages (based on simple string matching)."
echo -e "${GREEN}The desert of Arrakis lies still. No worms, no tainted spice.${NC}"
else
UNIQUE_GLOBAL_PACKAGES=$(printf '%s\n' "${GLOBAL_FOUND_PACKAGES[@]}" | sort -u)
UNIQUE_COUNT=$(printf '%s\n' "${UNIQUE_GLOBAL_PACKAGES}" | wc -l | tr -d ' ')
echo -e "${RED}⚠ WARNING - Affected packages detected across your projects.${NC}"
echo "Unique affected packages found: ${UNIQUE_COUNT}"
echo ""
echo "List of unique affected packages found:"
printf ' %s\n' ${UNIQUE_GLOBAL_PACKAGES}
echo ""
echo -e "${YELLOW}Recommendation:${NC}"
echo " Review these packages in each project and consider removing, replacing,"
echo " or upgrading them according to security advisories."
echo ""
echo -e "${RED}The worm has been sighted. It is unwise to ignore it.${NC}"
fi
echo "--------------------------------------------------"
DEV_ENV_DIR="${HOME}/.dev-env"
if [ -d "${DEV_ENV_DIR}" ]; then
echo -e "${RED}⚠ Detected directory: ${DEV_ENV_DIR}${NC}"
echo "This path is sometimes created by suspicious tooling (for example via Bun \$\"\$\" mkdir -p \$HOME/.dev-env)."
echo "Inspect its contents and remove it if you did not intentionally create it."
else
echo -e "${GREEN}No ${DEV_ENV_DIR} directory detected.${NC}"
fi
echo "=================================================="
echo ""
echo "Total packages checked: ${#AFFECTED_PACKAGES[@]}"
echo ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment