Skip to content

Instantly share code, notes, and snippets.

@nrajlekhak
Created May 12, 2026 04:52
Show Gist options
  • Select an option

  • Save nrajlekhak/84bda8dc75e9212c7699a79bb34fa4dc to your computer and use it in GitHub Desktop.

Select an option

Save nrajlekhak/84bda8dc75e9212c7699a79bb34fa4dc to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# detect-mini-shai-hulud.sh
#
# Scans every project under the CWD for npm packages compromised in the
# "Mini Shai-Hulud" supply-chain attack (npm ecosystem, 2026).
#
# Compromised package list source: StepSecurity blog
# https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem
# @tanstack/* patched versions cross-verified against GitHub Security Advisory:
# https://github.com/TanStack/router/security/advisories/GHSA-g7cv-rxg3-hmpx
#
# Usage:
# cd ~/projects
# bash detect-mini-shai-hulud.sh
#
# Scans: package-lock.json, yarn.lock, pnpm-lock.yaml (skips node_modules)
# Note: bun.lockb is binary — for Bun projects: bun pm ls | less
# ─────────────────────────────────────────────────────────────────────────────
set -euo pipefail
# ─── Compromised packages ────────────────────────────────────────────────────
# Format: "<package>|<bad_version_1>[,<bad_version_2>,...]|<fix_message>"
# Add new entries here as advisories drop.
VULN_LIST=(
"@uipath/docsai-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/packager-tool-apiworkflow|0.0.19|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/packager-tool-workflowcompiler-browser|0.0.34|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/packager-tool-functions|0.1.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/agent.sdk|0.0.18|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/filesystem|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/admin-tool|0.1.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/llmgw-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tanstack/arktype-adapter|1.166.12,1.166.15|upgrade to 1.166.16"
"@tanstack/eslint-plugin-router|1.161.9,1.161.12|upgrade to 1.161.13"
"@tanstack/eslint-plugin-start|0.0.4,0.0.7|upgrade to 0.0.8"
"@tanstack/history|1.161.9,1.161.12|upgrade to 1.161.13"
"@tanstack/nitro-v2-vite-plugin|1.154.12,1.154.15|upgrade to 1.154.16"
"@tanstack/react-router|1.169.5,1.169.8|upgrade to 1.169.9"
"@tanstack/react-router-devtools|1.166.16,1.166.19|upgrade to 1.166.20"
"@tanstack/react-router-ssr-query|1.166.15,1.166.18|upgrade to 1.166.19"
"@tanstack/react-start|1.167.68,1.167.71|upgrade to 1.167.72"
"@tanstack/react-start-client|1.166.51,1.166.54|upgrade to 1.166.55"
"@tanstack/react-start-rsc|0.0.47,0.0.50|upgrade to 0.0.51"
"@tanstack/react-start-server|1.166.55,1.166.58|upgrade to 1.166.59"
"@tanstack/router-cli|1.166.46,1.166.49|upgrade to 1.166.50"
"@tanstack/router-core|1.169.5,1.169.8|upgrade to 1.169.9"
"@tanstack/router-devtools|1.166.16,1.166.19|upgrade to 1.166.20"
"@tanstack/router-devtools-core|1.167.6,1.167.9|upgrade to 1.167.10"
"@tanstack/router-generator|1.166.45,1.166.48|upgrade to 1.166.49"
"@tanstack/router-plugin|1.167.38,1.167.41|upgrade to 1.167.42"
"@tanstack/router-ssr-query-core|1.168.3,1.168.6|upgrade to 1.168.7"
"@tanstack/router-utils|1.161.11,1.161.14|upgrade to 1.161.15"
"@tanstack/router-vite-plugin|1.166.53,1.166.56|upgrade to 1.166.57"
"@tanstack/solid-router|1.169.5,1.169.8|upgrade to 1.169.9"
"@tanstack/solid-router-devtools|1.166.16,1.166.19|upgrade to 1.166.20"
"@tanstack/solid-router-ssr-query|1.166.15,1.166.18|upgrade to 1.166.19"
"@tanstack/solid-start|1.167.65,1.167.68|upgrade to 1.167.69"
"@tanstack/solid-start-client|1.166.50,1.166.53|upgrade to 1.166.54"
"@tanstack/solid-start-server|1.166.54,1.166.57|upgrade to 1.166.58"
"@tanstack/start-client-core|1.168.5,1.168.8|upgrade to 1.168.9"
"@tanstack/start-fn-stubs|1.161.9,1.161.12|upgrade to 1.161.13"
"@tanstack/start-plugin-core|1.169.23,1.169.26|upgrade to 1.169.27"
"@tanstack/start-server-core|1.167.33,1.167.36|upgrade to 1.167.37"
"@tanstack/start-static-server-functions|1.166.44,1.166.47|upgrade to 1.166.48"
"@tanstack/start-storage-context|1.166.38,1.166.41|upgrade to 1.166.42"
"@tanstack/valibot-adapter|1.166.12,1.166.15|upgrade to 1.166.16"
"@tanstack/virtual-file-routes|1.161.10,1.161.13|upgrade to 1.161.14"
"@tanstack/vue-router|1.169.5,1.169.8|upgrade to 1.169.9"
"@tanstack/vue-router-devtools|1.166.16,1.166.19|upgrade to 1.166.20"
"@tanstack/vue-router-ssr-query|1.166.15,1.166.18|upgrade to 1.166.19"
"@tanstack/vue-start|1.167.61,1.167.64|upgrade to 1.167.65"
"@tanstack/vue-start-client|1.166.46,1.166.49|upgrade to 1.166.50"
"@tanstack/vue-start-server|1.166.50,1.166.53|upgrade to 1.166.54"
"@tanstack/zod-adapter|1.166.12,1.166.15|upgrade to 1.166.16"
"@draftauth/client|0.2.1,0.2.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@draftauth/core|0.13.1,0.13.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@draftlab/auth|0.24.1,0.24.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@draftlab/auth-router|0.5.1,0.5.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@draftlab/db|0.16.1,0.16.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@taskflow-corp/cli|0.1.24,0.1.25,0.1.26,0.1.27,0.1.28,0.1.29|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tolka/cli|1.0.2,1.0.3,1.0.4,1.0.6|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/access-policy-sdk|0.3.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/access-policy-tool|0.3.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/agent-sdk|1.0.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/agent-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/aops-policy-tool|0.3.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/ap-chat|1.5.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/api-workflow-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/apollo-core|5.9.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/apollo-react|4.24.5|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/apollo-wind|2.16.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/auth|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/case-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/cli|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/codedagent-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/codedagents-tool|0.1.12|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/codedapp-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/common|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/context-grounding-tool|0.1.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/data-fabric-tool|1.0.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/flow-tool|1.0.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/functions-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/gov-tool|0.3.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/identity-tool|0.1.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/insights-sdk|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/insights-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/integrationservice-sdk|1.0.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/integrationservice-tool|1.0.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/maestro-sdk|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/maestro-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/orchestrator-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/packager-tool-bpmn|0.0.9|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/packager-tool-case|0.0.9|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/packager-tool-connector|0.0.19|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/packager-tool-flow|0.0.19|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/packager-tool-webapp|1.0.6|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/packager-tool-workflowcompiler|0.0.16|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/platform-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/project-packager|1.1.16|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/resource-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/resourcecatalog-tool|0.1.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/resources-tool|0.1.11|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/robot|1.3.4|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/rpa-legacy-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/rpa-tool|0.9.5|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/solution-packager|0.0.35|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/solution-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/solutionpackager-sdk|1.0.11|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/solutionpackager-tool-core|0.0.34|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/tasks-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/telemetry|0.0.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/test-manager-tool|1.0.2|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/tool-workflowcompiler|0.0.12|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/traces-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/ui-widgets-multi-file-upload|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/uipath-python-bridge|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/vertical-solutions-tool|1.0.1|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/vss|0.1.6|remove/replace — no known clean patched version; rotate any creds touched at install"
"@uipath/widget.sdk|1.2.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"safe-action|0.8.3,0.8.4|remove/replace — no known clean patched version; rotate any creds touched at install"
"@supersurkhet/cli|0.0.2,0.0.3,0.0.4,0.0.5,0.0.6,0.0.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"@supersurkhet/sdk|0.0.2,0.0.3,0.0.4,0.0.5,0.0.6,0.0.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"cmux-agent-mcp|0.1.3,0.1.4,0.1.5,0.1.6,0.1.7,0.1.8|remove/replace — no known clean patched version; rotate any creds touched at install"
"git-git-git|1.0.8,1.0.9,1.0.10,1.0.12|remove/replace — no known clean patched version; rotate any creds touched at install"
"git-branch-selector|1.3.3,1.3.4,1.3.5,1.3.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"nextmove-mcp|0.1.3,0.1.4,0.1.5,0.1.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"@beproduct/nestjs-auth|0.1.2,0.1.3,0.1.4,0.1.5,0.1.6,0.1.7,0.1.8,0.1.9,0.1.10,0.1.11,0.1.12,0.1.13,0.1.14,0.1.15,0.1.16,0.1.17,0.1.19|remove/replace — no known clean patched version; rotate any creds touched at install"
"@dirigible-ai/sdk|0.6.2,0.6.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@ml-toolkit-ts/preprocessing|1.0.2,1.0.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@ml-toolkit-ts/xgboost|1.0.3,1.0.4|remove/replace — no known clean patched version; rotate any creds touched at install"
"agentwork-cli|0.1.4,0.1.5|remove/replace — no known clean patched version; rotate any creds touched at install"
"ml-toolkit-ts|1.0.4,1.0.5|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/airport-data|0.7.4,0.7.5,0.7.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/airports|0.6.2,0.6.3,0.6.5|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/airspace|0.8.1,0.8.2,0.8.4|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/airspace-data|0.5.3,0.5.4,0.5.6|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/airway-data|0.5.4,0.5.5,0.5.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/airways|0.4.2,0.4.3,0.4.5|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/fix-data|0.6.4,0.6.5,0.6.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/fixes|0.3.2,0.3.3,0.3.5|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/flight-math|0.5.4,0.5.5,0.5.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/flightplan|0.5.2,0.5.3,0.5.5|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/geo|0.4.4,0.4.5,0.4.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/icao-registry|0.5.2,0.5.3,0.5.5|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/icao-registry-data|0.8.4,0.8.5,0.8.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/mcp|0.9.1,0.9.2,0.9.4|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/navaid-data|0.6.4,0.6.5,0.6.7|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/navaids|0.4.2,0.4.3,0.4.5|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/notams|0.3.6,0.3.7,0.3.9|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/procedure-data|0.7.3,0.7.4,0.7.6|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/procedures|0.5.2,0.5.3,0.5.5|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/types|0.8.1,0.8.2,0.8.4|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/units|0.4.3,0.4.4,0.4.6|remove/replace — no known clean patched version; rotate any creds touched at install"
"@squawk/weather|0.5.6,0.5.7,0.5.9|remove/replace — no known clean patched version; rotate any creds touched at install"
"wot-api|0.8.1,0.8.2,0.8.4|remove/replace — no known clean patched version; rotate any creds touched at install"
"cross-stitch|1.1.3,1.1.4,1.1.6|remove/replace — no known clean patched version; rotate any creds touched at install"
"ts-dna|3.0.1,3.0.2,3.0.4|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tallyui/components|1.0.1,1.0.2,1.0.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tallyui/connector-medusa|1.0.1,1.0.2,1.0.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tallyui/connector-shopify|1.0.1,1.0.2,1.0.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tallyui/connector-vendure|1.0.1,1.0.2,1.0.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tallyui/connector-woocommerce|1.0.1,1.0.2,1.0.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tallyui/core|0.2.1,0.2.2,0.2.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tallyui/database|1.0.1,1.0.2,1.0.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tallyui/pos|0.1.1,0.1.2,0.1.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tallyui/storage-sqlite|0.2.1,0.2.2,0.2.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@tallyui/theme|0.2.1,0.2.2,0.2.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@mesadev/rest|0.28.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@mesadev/saguaro|0.4.22|remove/replace — no known clean patched version; rotate any creds touched at install"
"@mesadev/sdk|0.28.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@mistralai/mistralai|2.2.3,2.2.4|remove/replace — no known clean patched version; rotate any creds touched at install"
"@mistralai/mistralai-azure|1.7.2,1.7.3|remove/replace — no known clean patched version; rotate any creds touched at install"
"@mistralai/mistralai-gcp|1.7.2,1.7.3|remove/replace — no known clean patched version; rotate any creds touched at install"
)
# ─────────────────────────────────────────────────────────────────────────────
# Serialize VULN_LIST to JSON for the per-lockfile Python parser
VULN_RAW=$(printf '%s\n' "${VULN_LIST[@]}")
export VULN_RAW
VULN_JSON=$(python3 -c '
import json, os
out = {}
for line in os.environ["VULN_RAW"].strip().split("\n"):
pkg, bad_csv, fix = line.split("|", 2)
out[pkg] = {"bad": bad_csv.split(","), "fix": fix}
print(json.dumps(out))
')
export VULN_JSON
NUM_PKGS=${#VULN_LIST[@]}
LOCKFILES=()
while IFS= read -r line; do
LOCKFILES+=("$line")
done < <(find . \( -name package-lock.json -o -name yarn.lock -o -name pnpm-lock.yaml \) -not -path '*/node_modules/*' 2>/dev/null | sort)
if [[ ${#LOCKFILES[@]} -eq 0 ]]; then
echo "No lock files found under $(pwd)"
exit 0
fi
echo "Scanning ${#LOCKFILES[@]} lock file(s) for $NUM_PKGS compromised packages (Mini Shai-Hulud campaign)..."
echo
TOTAL_HITS=0
AFFECTED_PROJECTS=()
for lock in "${LOCKFILES[@]}"; do
project=$(dirname "$lock" | sed 's|^\./||')
base=$(basename "$lock")
hits=$(LOCK_PATH="$lock" LOCK_TYPE="$base" python3 - <<'PY'
import json, os, re, sys
vuln = json.loads(os.environ['VULN_JSON'])
path = os.environ['LOCK_PATH']
kind = os.environ['LOCK_TYPE']
found = [] # list of (pkg, version, fix)
def check(pkg, ver):
if pkg in vuln and ver in vuln[pkg]['bad']:
found.append((pkg, ver, vuln[pkg]['fix']))
# Pre-built alternation of all watched package names for fast scanning
pkg_re_alt = '|'.join(re.escape(p) for p in vuln.keys())
try:
with open(path, 'r', encoding='utf-8', errors='replace') as f:
content = f.read()
except Exception as e:
print(f"ERROR_READING:{e}", file=sys.stderr)
sys.exit(0)
if kind == 'package-lock.json':
try:
d = json.loads(content)
except json.JSONDecodeError:
sys.exit(0)
# npm v7+ "packages" map
pkg_suffix_re = re.compile(r'node_modules/(' + pkg_re_alt + r')$')
for key, meta in (d.get('packages') or {}).items():
m = pkg_suffix_re.search(key)
if m:
check(m.group(1), meta.get('version', ''))
# legacy "dependencies" tree (npm v6)
def walk(deps):
for name, meta in (deps or {}).items():
if name in vuln:
check(name, meta.get('version', ''))
walk(meta.get('dependencies'))
walk(d.get('dependencies'))
elif kind == 'yarn.lock':
# Yarn v1 / Berry blocks
blocks = re.split(r'\n(?=[^\s])', content)
header_pkg_re = re.compile(r'"?(' + pkg_re_alt + r')@')
ver_line_re = re.compile(r'^\s+version\s+"([^"]+)"', re.M)
for block in blocks:
first = block.split('\n', 1)[0]
pkgs_in_header = header_pkg_re.findall(first)
if not pkgs_in_header:
continue
ver_match = ver_line_re.search(block)
if not ver_match:
continue
version = ver_match.group(1)
for pkg in set(pkgs_in_header):
check(pkg, version)
elif kind == 'pnpm-lock.yaml':
# pnpm: every package@version reference is captured
occ_re = re.compile(r'(' + pkg_re_alt + r')@([0-9][0-9a-zA-Z.+-]*)')
for m in occ_re.finditer(content):
check(m.group(1), m.group(2))
seen = set()
for pkg, ver, fix in found:
key = (pkg, ver)
if key in seen: continue
seen.add(key)
print(f"{pkg}|{ver}|{fix}")
PY
)
if [[ -n "$hits" ]]; then
AFFECTED_PROJECTS+=("$project")
echo "$project ($base)"
while IFS='|' read -r pkg ver fix; do
echo " $pkg@$ver$fix"
TOTAL_HITS=$((TOTAL_HITS + 1))
done <<< "$hits"
echo
fi
done
echo "──────────────────────────────────────────────"
if [[ $TOTAL_HITS -eq 0 ]]; then
echo "✅ No compromised packages found in ${#LOCKFILES[@]} lock file(s)."
else
uniq_projects=$(printf '%s\n' "${AFFECTED_PROJECTS[@]}" | sort -u | wc -l | tr -d ' ')
echo "❌ Found $TOTAL_HITS compromised dependency entries across $uniq_projects project(s)."
echo
echo "Remediation:"
echo " 1. Upgrade/remove each affected package per the message above."
echo " 2. Delete node_modules and the lock file, then reinstall."
echo " 3. Rotate any secrets accessible to your dev/build/CI environment"
echo " (the worm exfiltrates env vars, .env files, cloud/GitHub/npm tokens, SSH keys)."
echo " 4. Audit CI logs for outbound calls to attacker-controlled GitHub repos."
fi
@taarimalta

taarimalta commented May 12, 2026

Copy link
Copy Markdown

Command to look through a folder recursively through all lock files and package files. Shows affected and non affected versions

find . -type f \( -name "package.json" -o -name "package-lock.json" -o -name "pnpm-lock.yaml" -o -name "yarn.lock" \) -exec grep -HoiE '"[^"]*(@tanstack/|draftlab|draftauth|taskflow-corp|tolka|uipath|opensearch-project|squawk|supersurkhet|mesadev|mistralai|tallyui|beproduct|dirigible-ai|ml-toolkit-ts|safe-action|cmux-agent-mcp|git-git-git|git-branch-selector|nextmove-mcp|agentwork-cli|wot-api|cross-stitch|ts-dna)[^"]*"[[:space:]]*:[[:space:]]*"[^"]+"|(@tanstack/|@?(draftlab|draftauth|taskflow-corp|tolka|uipath|opensearch-project|squawk|supersurkhet|mesadev|mistralai|tallyui|beproduct|dirigible-ai|ml-toolkit-ts|safe-action|cmux-agent-mcp|git-git-git|git-branch-selector|nextmove-mcp|agentwork-cli|wot-api|cross-stitch|ts-dna))[a-zA-Z0-9._/-]*@[^"[:space:],:]+' {} + | sort -u

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