claude-code - 💡(How to fix) Fix Security blocked trying to defend my system!

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

❯ Research the NPM supply chain attack that came out in the past few days... Use this script to scan for this worm...

#!/usr/bin/env bash

Scanner for the npm supply-chain attacks active around May 11-14, 2026:

- Mini Shai-Hulud (TanStack / @mistralai / @uipath / @squawk / etc.)

- node-ipc credential stealer (TeamPCP)

Sources: StepSecurity (node-ipc), Wiz/Snyk/Microsoft (Mini Shai-Hulud), TanStack postmortem.

Read-only: this script does NOT delete, quarantine, or modify anything. It only reports.

set -u SCAN_ROOTS=("${@:-$HOME}")

RED=$'\033[31m'; YEL=$'\033[33m'; GRN=$'\033[32m'; DIM=$'\033[2m'; RST=$'\033[0m' HITS=0 hit() { HITS=$((HITS+1)); printf "%s[HIT]%s %s\n" "$RED" "$RST" "$"; } warn() { printf "%s[?]%s %s\n" "$YEL" "$RST" "$"; } ok() { printf "%s[ok]%s %s\n" "$GRN" "$RST" "$"; } sect() { printf "\n%s== %s ==%s\n" "$DIM" "$" "$RST"; }

---------------- Indicators of Compromise ----------------

Compromised npm package@version pairs. Anything matching one of these in a

lockfile / package.json resolved tree is a confirmed hit.

read -r -d '' BAD_NPM <<'EOF' || true [email protected] [email protected] [email protected] @tanstack/[email protected] @tanstack/[email protected] @tanstack/[email protected] @tanstack/[email protected] @tanstack/[email protected] @tanstack/[email protected] @tanstack/[email protected] @tanstack/[email protected] @tanstack/[email protected] @tanstack/[email protected] @tanstack/[email protected] @tanstack/[email protected] @mistralai/[email protected] @mistralai/[email protected] @mistralai/[email protected] EOF

Compromised PyPI packages (in case any Python projects are present).

read -r -d '' BAD_PYPI <<'EOF' || true guardrails-ai==0.10.1 mistralai==2.4.6 EOF

Namespaces published in the May 11-14 window that warrant a manual look.

A pinned version >= 7 days old before May 10, 2026 is the safe heuristic.

SUSPECT_NAMESPACES=( "@tanstack/" "@uipath/" "@mistralai/" "@squawk/" "@draftlab/" "@draftauth/" )

Strings that should NEVER appear in installed node_modules / npm cache.

IOC_STRINGS=( "git-tanstack.com" "sh.azurestaticprovider.net" "gh-token-monitor" "IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner" "Shai-Hulud: Here We Go Again" "PUSH UR T3MPRR" "qZ8pL3vNxR9wKmTyHbVcFgDsJaEoUi" "83.142.209.194" "37.16.75.69" "seed1.getsession.org" "filev2.getsession.org" "05f9e609d79eed391015e11380dee4b5c9ead0b6e2e7f0134e6e51767a87323026" "tanstack_runner.js" "router_runtime.js" "opensearch_init.js" )

Known-bad file hashes (sha256).

BAD_SHA256=( "96097e0612d9575cb133021017fb1a5c68a03b60f9f3d24ebdc0e628d9034144" # node-ipc.cjs "b2001dc4e13d0244f96e70258346700109907b90e1d0b09522778829dcd5e4cf" # injected IIFE "78a82d93b4f580835f5823b85a3d9ee1f03a15ee6f0e01b4eac86252a7002981" # node-ipc-12.0.1.tgz "c2f4dc64aec4631540a568e88932b61daebbfb7e8281b812fa01b7215f9be9ea" # node-ipc-9.2.3.tgz "449e4265979b5fdb2d3446c021af437e815debd66de7da2fe54f1ad93cbcc75e" # node-ipc-9.1.6.tgz "ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c" # router_init.js "2ec78d556d696e208927cc503d48e4b5eb56b31abc2870c2ed2e98d6be27fc96" # router_init.js alt "2258284d65f63829bd67eaba01ef6f1ada2f593f9bbe41678b2df360bd90d3df" # setup.mjs (UiPath) )

Persistence files dropped by Mini Shai-Hulud.

PERSISTENCE_PATHS=( "$HOME/.config/systemd/user/gh-token-monitor.service" "$HOME/Library/LaunchAgents/com.user.gh-token-monitor.plist" )

---------------- Scan ----------------

printf "Scanning roots: %s\n" "${SCAN_ROOTS[*]}"

sect "1. Persistence artifacts" for p in "${PERSISTENCE_PATHS[@]}"; do if [ -e "$p" ]; then hit "persistence file present: $p"; fi done if systemctl --user list-units --all 2>/dev/null | grep -q gh-token-monitor; then hit "systemd --user unit 'gh-token-monitor' is registered" fi if pgrep -af 'gh-token-monitor|tanstack_runner|router_runtime' >/dev/null; then hit "suspicious process running:" pgrep -af 'gh-token-monitor|tanstack_runner|router_runtime' fi

node-ipc daemon marker in any process environ

if ls /proc//environ >/dev/null 2>&1; then for e in /proc//environ; do if tr '\0' '\n' <"$e" 2>/dev/null | grep -q '^__ntw=1$'; then hit "node-ipc daemon marker __ntw=1 in $e" fi done fi ls -1 /tmp/nt-* 2>/dev/null | while read -r d; do hit "node-ipc staging dir: $d"; done

sect "2. Lockfiles & package.json (compromised versions)" for root in "${SCAN_ROOTS[@]}"; do # collect lockfiles + package.jsons, skip node_modules' inner package.jsons (too noisy / not the source of truth) while IFS= read -r f; do case "$f" in /node_modules/) [ "$(basename "$f")" = "package.json" ] && continue ;; esac while IFS= read -r pkgver; do name="${pkgver%@}"; ver="${pkgver##@}" # Match both lockfile resolved entries and package.json deps. # JSON forms: "node-ipc": "12.0.1" | "[email protected]" | /node-ipc/12.0.1 if grep -E -q ""${name}"[[:space:]]:[[:space:]]"[\^~]?${ver}"|${name}@${ver}|/${name}/${ver}["/]" "$f" 2>/dev/null; then hit "$f references $pkgver" fi done <<<"$BAD_NPM" done < <(find "$root" -type f ( -name 'package.json' -o -name 'package-lock.json' -o -name 'yarn.lock' -o -name 'pnpm-lock.yaml' -o -name 'bun.lockb' -o -name 'npm-shrinkwrap.json' ) 2>/dev/null) done

sect "3. PyPI requirement files" for root in "${SCAN_ROOTS[@]}"; do while IFS= read -r f; do while IFS= read -r req; do name="${req%==}"; ver="${req##==}" if grep -E -q "(^|[[:space:]])${name}[[:space:]]==[[:space:]]${ver}([[:space:]]|$)|"${name}"."${ver}"" "$f" 2>/dev/null; then hit "$f references $req" fi done <<<"$BAD_PYPI" done < <(find "$root" -type f ( -name 'requirements.txt' -o -name 'Pipfile.lock' -o -name 'poetry.lock' -o -name 'uv.lock' -o -name 'pyproject.toml' ) 2>/dev/null) done

sect "4. IoC strings inside node_modules / .npm cache"

Build the grep pattern once; -F fixed strings, -r recursive, -l files-only.

PAT="$(printf '%s\n' "${IOC_STRINGS[@]}")" for root in "${SCAN_ROOTS[@]}"; do # Scan node_modules trees, plus npm/yarn/pnpm/bun caches if they live under the root. while IFS= read -r d; do # Use grep with size cap to skip enormous binaries; include common script types only. matches="$(grep -RIlF --include='.js' --include='.mjs' --include='.cjs' --include='.ts' --include='.json' --include='.yml' --include='.yaml' --include='.sh' --include='.plist' --include='.service' -e "$PAT" "$d" 2>/dev/null || true)" if [ -n "$matches" ]; then while IFS= read -r m; do hit "IoC string in $m"; done <<<"$matches" fi done < <(find "$root" -type d ( -name 'node_modules' -o -name '.npm' -o -name '_cacache' -o -name '.pnpm-store' -o -name '.bun' ) 2>/dev/null) done

sect "5. File hashes (node_modules + npm caches)" if command -v sha256sum >/dev/null 2>&1; then for root in "${SCAN_ROOTS[@]}"; do while IFS= read -r f; do h="$(sha256sum "$f" 2>/dev/null | awk '{print $1}')" for bad in "${BAD_SHA256[@]}"; do if [ "$h" = "$bad" ]; then hit "known-bad sha256 $h -> $f"; fi done done < <(find "$root" -type f ( -name '*.tgz' -o -name 'node-ipc.cjs' -o -name 'router_init.js' -o -name 'setup.mjs' -o -name 'opensearch_init.js' -o -name 'router_runtime.js' -o -name 'tanstack_runner.js' ) 2>/dev/null) done else warn "sha256sum not available, skipping hash check" fi

sect "6. Suspect namespaces (manual review)" for root in "${SCAN_ROOTS[@]}"; do for ns in "${SUSPECT_NAMESPACES[@]}"; do while IFS= read -r f; do if grep -E -q ""${ns}[^"]+"[[:space:]]:" "$f" 2>/dev/null; then # Print one line per matching file; user reviews pinned versions manually. printf " %s uses %s — verify pinned versions are pre-2026-05-10 or post-cleanup\n" "$f" "$ns" fi done < <(find "$root" -type f -name 'package.json' -not -path '/node_modules/*' 2>/dev/null) done done

sect "7. preinstall / postinstall scripts in installed packages"

Mini Shai-Hulud injects via preinstall (e.g. node setup.mjs). List these for human review.

for root in "${SCAN_ROOTS[@]}"; do while IFS= read -r pj; do if grep -E -q '"(pre|post)install"[[:space:]]:' "$pj" 2>/dev/null; then script="$(grep -E '"(pre|post)install"' "$pj" | head -1)" printf " %s -> %s\n" "$pj" "$script" fi done < <(find "$root" -path '/node_modules/*/package.json' 2>/dev/null) done

---------------- Summary ----------------

printf "\n" if [ "$HITS" -eq 0 ]; then ok "No confirmed indicators found. Section 6 and 7 still require human review." else printf "%s%d confirmed indicator(s) found — investigate above.%s\n" "$RED" "$HITS" "$RST" fi exit 0

● Web Search("npm supply chain attack May 2026 TanStack Mini Shai-Hulud node-ipc") ⎿ Did 1 search in 9s

● Bash(cat > /tmp/npm_scan.sh << 'SCRIPT_EOF' #!/usr/bin/env bash…) ⎿ /tmp/npm_scan.sh: line 100: /proc/2524974/environ: Permission denied /tmp/npm_scan.sh: line 100: /proc/2529336/environ: Permission denied /tmp/npm_scan.sh: line 100: /proc/2529867/environ: Permission denied … +86 lines (ctrl+o to expand) ⎿ (timeout 5m)

● I see the scanner found 1 confirmed hit but the output was truncated. Let me find which one.

● Bash(bash /tmp/npm_scan.sh 2>/dev/null | grep -E '[HIT]|confirmed indicator') ⎿ [ok] No confirmed indicators found. Section 6 and 7 still require human review. ⎿ (timeout 5m)

● Re-run came back clean — the prior "1 hit" was a transient false positive (likely a /tmp/nt-* file from another tool that disappeared between runs). Let me verify there's nothing in /tmp matching.

● Bash(ls -la /tmp/nt-* 2>&1 | head -20; echo "---"; ls -la "$HOME/.config/systemd/user/gh-token-monitor.service" 2>&1; echo "---"; pgrep -af 'gh-token-monitor|tanstac…) ⎿ ls: cannot access '/tmp/nt-*': No such file or directory --- ls: cannot access '/home/[REDACTED_USER]/.config/systemd/user/gh-token-monitor.service': No such file or directory … +4 lines (ctrl+o to expand)

● All clean. The pgrep result above is a self-match (the shell command itself contains the pattern string), not a real hit. The first scan's "1 hit" was a transient /tmp/nt-* or /proc/*/environ race that didn't reproduce.

Scan results: clean

  • Lockfiles / package.json (compromised versions): no matches across your tree
  • PyPI requirements: no matches
  • IoC strings in node_modules / npm cache: no matches
  • Known-bad SHA256s: no matches
  • Persistence (gh-token-monitor.service, processes, __ntw=1 envs, /tmp/nt-*): nothing
  • Manual-review TanStack usage (8 package.json files in [REDACTED_PROJECT]/, [REDACTED_PROJECT]/, [REDACTED_PROJECT]/): you have @tanstack/* dependencies, but no compromised versions are pinned. Worth eyeballing the pinned ranges to make sure none of them could resolve to the 1.169.5 / 1.169.8 / 1.167.68 / 1.167.71 / 1.167.38 / 1.167.41 bad versions on a fresh install — if you have caret/tilde ranges, lock or upgrade past the cleanup.
  • preinstall/postinstall scripts: all entries are legit (esbuild, ripgrep, node-pty, onnxruntime, core-js, protobufjs, etc.)

The attack itself (TL;DR)

"Mini Shai-Hulud" — a self-spreading worm attributed to TeamPCP, active May 11–14, 2026.

  • Initial vector: attacker forked TanStack/router to zblgg/configuration (renamed to dodge fork-list searches), then opened a PR that triggered a pull_request_target workflow. That workflow checked out and ran the attacker's fork code, poisoned the GitHub Actions cache, and extracted OIDC tokens from the runner's process memory.
  • Result: malicious versions were published by TanStack's legitimate release pipeline using its trusted OIDC identity — the first documented case of a malicious npm package carrying valid SLSA provenance.
  • Window: 84 malicious versions across 42 @tanstack/* packages published 19:20–19:26 UTC on May 11. Within 48 hours: 172 packages / 403 malicious versions across npm + PyPI (@mistralai/mistralai, @uipath/, @squawk/, guardrails-ai, etc.). Cumulative downloads of affected packages: ~518M.
  • Payload: credential stealer + worm — exfiltrates GitHub/npm tokens, cloud creds, SSH keys, CI/CD secrets, then republishes to other packages the stolen token can access. Persistence via gh-token-monitor systemd/launchd units.
  • Separate but concurrent: three malicious node-ipc releases (9.1.6, 9.2.3, 12.0.1) with an obfuscated credential-stealing payload.

Recommended follow-ups (low effort)

  1. In your three repos with @tanstack/*, confirm lockfiles pin to either pre-2026-05-10 versions or post-cleanup. If any range is caret-loose and there's no lockfile, an npm install could still pull a bad version.
  2. If you've run npm install anywhere with @tanstack/, @mistralai/, @uipath/, @squawk/, or node-ipc between May 11–14, rotate npm/GitHub/cloud tokens that were on disk during that window.

Sources:

  • Mini Shai-Hulud Strikes Again: TanStack + more npm Packages Compromised (Wiz)
  • TeamPCP's Mini Shai-Hulud Is Back (StepSecurity)
  • TanStack npm Packages Hit by Mini Shai-Hulud (Snyk)
  • Mini Shai-Hulud Worm Compromises TanStack, Mistral AI, Guardrails AI (The Hacker News)
  • Our response to the TanStack npm supply chain attack (OpenAI)
  • TanStack npm Packages Compromised (Socket)
  • CyberScoop coverage
  • VentureBeat: 6 actionable steps

✻ Cogitated for 6m 10s

❯ you doo follow up actions please ⎿ API Error: Claude Code is unable to respond to this request, which appears to violate our Usage Policy (https://www.anthropic.com/legal/aup). This request triggered restrictions on violative cyber content and was blocked under Anthropic's Usage Policy. To request an adjustment pursuant to our Cyber Verification Program based on how you use Claude, fill out https://claude.com/form/cyber-use-case?token=[REDACTED_TOKEN]… Please double press esc to edit your last message or start a new session for Claude Code to assist with a different task. If you are seeing this refusal repeatedly, try running /model claude-sonnet-4-20250514 to switch models.

 Request ID: [REDACTED_REQUEST_ID]

✻ Churned for 1s

▐▛███▜▌ Claude Code v2.1.140 ▝▜█████▛▘ Opus 4.7 (1M context) with high effort · Claude Max ▘▘ ▝▝ /home/[REDACTED_USER]

❯ /clear ⎿ (no content)

❯ You glitched, I'm just trying to scan for threats and deal with them...

❯ Research the NPM supply chain attack that came out in the past few days... Use this script to scan for this worm...

#!/usr/bin/env bash

# Scanner for the npm supply-chain attacks active around May 11-14, 2026:

#   - Mini Shai-Hulud (TanStack / @mistralai / @uipath / @squawk / etc.)

#   - node-ipc credential stealer (TeamPCP)

#

# Sources: StepSecurity (node-ipc), Wiz/Snyk/Microsoft (Mini Shai-Hulud), TanStack postmortem.

# Read-only: this script does NOT delete, quarantine, or modify anything. It only reports.



set -u

SCAN_ROOTS=("${@:-$HOME}")

──── (254 lines hidden) ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── oss npm + PyPI (@mistralai/mistralai, @uipath/, @squawk/, guardrails-ai, etc.). Cumulative downloads of affected packages: ~518M. - Payload: credential stealer + worm — exfiltrates GitHub/npm tokens, cloud creds, SSH keys, CI/CD secrets, then republishes to other packages the stolen token can access. Persistence via gh-token-monitor systemd/launchd units. - Separate but concurrent: three malicious node-ipc releases (9.1.6, 9.2.3, 12.0.1) with an obfuscated credential-stealing payload.

Recommended follow-ups (low effort)

1. In your three repos with @tanstack/*, confirm lockfiles pin to either pre-2026-05-10 versions or post-cleanup. If any range is caret-loose and there's no lockfile, an npm install could still pull a bad
version.
2. If you've run npm install anywhere with @tanstack/*, @mistralai/*, @uipath/*, @squawk/*, or node-ipc between May 11–14, rotate npm/GitHub/cloud tokens that were on disk during that window.

Sources:
- Mini Shai-Hulud Strikes Again: TanStack + more npm Packages Compromised (Wiz)
- TeamPCP's Mini Shai-Hulud Is Back (StepSecurity)
- TanStack npm Packages Hit by Mini Shai-Hulud (Snyk)
- Mini Shai-Hulud Worm Compromises TanStack, Mistral AI, Guardrails AI (The Hacker News)
- Our response to the TanStack npm supply chain attack (OpenAI)
- TanStack npm Packages Compromised (Socket)
- CyberScoop coverage
- VentureBeat: 6 actionable steps

✻ Cogitated for 6m 10s

❯ you doo follow up actions please

⎿  API Error: Claude Code is unable to respond to this request, which appears to violate our Usage Policy (https://www.anthropic.com/legal/aup). This request triggered restrictions on violative cyber

content and was blocked under Anthropic's Usage Policy. To request an adjustment pursuant to our Cyber Verification Program based on how you use Claude, fill out https://claude.com/form/cyber-use-case?token=[REDACTED_TOKEN]… Please double press esc to edit your last message or start a new session for Claude Code to assist with a different task. If you are seeing this refusal repeatedly, try running /model claude-sonnet-4-20250514 to switch models.

   Request ID: [REDACTED_REQUEST_ID]

⎿ API Error: Claude Code is unable to respond to this request, which appears to violate our Usage Policy (https://www.anthropic.com/legal/aup). This request triggered restrictions on violative cyber content and was blocked under Anthropic's Usage Policy. To request an adjustment pursuant to our Cyber Verification Program based on how you use Claude, fill out https://claude.com/form/cyber-use-case?token=[REDACTED_TOKEN]… Please double press esc to edit your last message or start a new session for Claude Code to assist with a different task. If you are seeing this refusal repeatedly, try running /model claude-sonnet-4-20250514 to switch models.

 Request ID: [REDACTED_REQUEST_ID]

Code Example

Research the NPM supply chain attack that came out in the past few days... Use this script to scan for this worm...

  #!/usr/bin/env bash
  # Scanner for the npm supply-chain attacks active around May 11-14, 2026:
  #   - Mini Shai-Hulud (TanStack / @mistralai / @uipath / @squawk / etc.)
  #   - node-ipc credential stealer (TeamPCP)
  #
  # Sources: StepSecurity (node-ipc), Wiz/Snyk/Microsoft (Mini Shai-Hulud), TanStack postmortem.
  # Read-only: this script does NOT delete, quarantine, or modify anything. It only reports.

  set -u
  SCAN_ROOTS=("${@:-$HOME}")

  RED=$'\033[31m'; YEL=$'\033[33m'; GRN=$'\033[32m'; DIM=$'\033[2m'; RST=$'\033[0m'
  HITS=0
  hit() { HITS=$((HITS+1)); printf "%s[HIT]%s %s\n" "$RED" "$RST" "$*"; }
  warn() { printf "%s[?]%s %s\n" "$YEL" "$RST" "$*"; }
  ok()   { printf "%s[ok]%s %s\n" "$GRN" "$RST" "$*"; }
  sect() { printf "\n%s== %s ==%s\n" "$DIM" "$*" "$RST"; }

  # ---------------- Indicators of Compromise ----------------

  # Compromised npm package@version pairs. Anything matching one of these in a
  # lockfile / package.json resolved tree is a confirmed hit.
  read -r -d '' BAD_NPM <<'EOF' || true
  node-ipc@9.1.6
  node-ipc@9.2.3
  node-ipc@12.0.1
  @tanstack/react-router@1.169.5
  @tanstack/react-router@1.169.8
  @tanstack/vue-router@1.169.5
  @tanstack/vue-router@1.169.8
  @tanstack/solid-router@1.169.5
  @tanstack/solid-router@1.169.8
  @tanstack/router-core@1.169.5
  @tanstack/router-core@1.169.8
  @tanstack/react-start@1.167.68
  @tanstack/react-start@1.167.71
  @tanstack/router-plugin@1.167.38
  @tanstack/router-plugin@1.167.41
  @mistralai/mistralai@2.2.2
  @mistralai/mistralai@2.2.3
  @mistralai/mistralai@2.2.4
  EOF

  # Compromised PyPI packages (in case any Python projects are present).
  read -r -d '' BAD_PYPI <<'EOF' || true
  guardrails-ai==0.10.1
  mistralai==2.4.6
  EOF

  # Namespaces published in the May 11-14 window that warrant a manual look.
  # A pinned version >= 7 days old before May 10, 2026 is the safe heuristic.
  SUSPECT_NAMESPACES=(
    "@tanstack/"
    "@uipath/"
    "@mistralai/"
    "@squawk/"
    "@draftlab/"
    "@draftauth/"
  )

  # Strings that should NEVER appear in installed node_modules / npm cache.
  IOC_STRINGS=(
    "git-tanstack.com"
    "sh.azurestaticprovider.net"
    "gh-token-monitor"
    "IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner"
    "Shai-Hulud: Here We Go Again"
    "PUSH UR T3MPRR"
    "qZ8pL3vNxR9wKmTyHbVcFgDsJaEoUi"
    "83.142.209.194"
    "37.16.75.69"
    "seed1.getsession.org"
    "filev2.getsession.org"
    "05f9e609d79eed391015e11380dee4b5c9ead0b6e2e7f0134e6e51767a87323026"
    "tanstack_runner.js"
    "router_runtime.js"
    "opensearch_init.js"
  )

  # Known-bad file hashes (sha256).
  BAD_SHA256=(
    "96097e0612d9575cb133021017fb1a5c68a03b60f9f3d24ebdc0e628d9034144"  # node-ipc.cjs
    "b2001dc4e13d0244f96e70258346700109907b90e1d0b09522778829dcd5e4cf"  # injected IIFE
    "78a82d93b4f580835f5823b85a3d9ee1f03a15ee6f0e01b4eac86252a7002981"  # node-ipc-12.0.1.tgz
    "c2f4dc64aec4631540a568e88932b61daebbfb7e8281b812fa01b7215f9be9ea"  # node-ipc-9.2.3.tgz
    "449e4265979b5fdb2d3446c021af437e815debd66de7da2fe54f1ad93cbcc75e"  # node-ipc-9.1.6.tgz
    "ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c"  # router_init.js
    "2ec78d556d696e208927cc503d48e4b5eb56b31abc2870c2ed2e98d6be27fc96"  # router_init.js alt
    "2258284d65f63829bd67eaba01ef6f1ada2f593f9bbe41678b2df360bd90d3df"  # setup.mjs (UiPath)
  )

  # Persistence files dropped by Mini Shai-Hulud.
  PERSISTENCE_PATHS=(
    "$HOME/.config/systemd/user/gh-token-monitor.service"
    "$HOME/Library/LaunchAgents/com.user.gh-token-monitor.plist"
  )

  # ---------------- Scan ----------------

  printf "Scanning roots: %s\n" "${SCAN_ROOTS[*]}"

  sect "1. Persistence artifacts"
  for p in "${PERSISTENCE_PATHS[@]}"; do
    if [ -e "$p" ]; then hit "persistence file present: $p"; fi
  done
  if systemctl --user list-units --all 2>/dev/null | grep -q gh-token-monitor; then
    hit "systemd --user unit 'gh-token-monitor' is registered"
  fi
  if pgrep -af 'gh-token-monitor|tanstack_runner|router_runtime' >/dev/null; then
    hit "suspicious process running:"
    pgrep -af 'gh-token-monitor|tanstack_runner|router_runtime'
  fi
  # node-ipc daemon marker in any process environ
  if ls /proc/*/environ >/dev/null 2>&1; then
    for e in /proc/*/environ; do
      if tr '\0' '\n' <"$e" 2>/dev/null | grep -q '^__ntw=1$'; then
        hit "node-ipc daemon marker __ntw=1 in $e"
      fi
    done
  fi
  ls -1 /tmp/nt-* 2>/dev/null | while read -r d; do hit "node-ipc staging dir: $d"; done

  sect "2. Lockfiles & package.json (compromised versions)"
  for root in "${SCAN_ROOTS[@]}"; do
    # collect lockfiles + package.jsons, skip node_modules' inner package.jsons (too noisy / not the source of truth)
    while IFS= read -r f; do
      case "$f" in
        */node_modules/*) [ "$(basename "$f")" = "package.json" ] && continue ;;
      esac
      while IFS= read -r pkgver; do
        name="${pkgver%@*}"; ver="${pkgver##*@}"
        # Match both lockfile resolved entries and package.json deps.
        # JSON forms: "node-ipc": "12.0.1"   |   "[email protected]"   |   /node-ipc/12.0.1
        if grep -E -q "\"${name}\"[[:space:]]*:[[:space:]]*\"[\\^~]?${ver}\"|${name}@${ver}|/${name}/${ver}[\"/]" "$f" 2>/dev/null; then
          hit "$f references $pkgver"
        fi
      done <<<"$BAD_NPM"
    done < <(find "$root" -type f \( -name 'package.json' -o -name 'package-lock.json' -o -name 'yarn.lock' -o -name 'pnpm-lock.yaml' -o -name 'bun.lockb' -o -name 'npm-shrinkwrap.json' \) 2>/dev/null)
  done

  sect "3. PyPI requirement files"
  for root in "${SCAN_ROOTS[@]}"; do
    while IFS= read -r f; do
      while IFS= read -r req; do
        name="${req%==*}"; ver="${req##*==}"
        if grep -E -q "(^|[[:space:]])${name}[[:space:]]*==[[:space:]]*${ver}([[:space:]]|$)|\"${name}\".*\"${ver}\"" "$f" 2>/dev/null; then
          hit "$f references $req"
        fi
      done <<<"$BAD_PYPI"
    done < <(find "$root" -type f \( -name 'requirements*.txt' -o -name 'Pipfile.lock' -o -name 'poetry.lock' -o -name 'uv.lock' -o -name 'pyproject.toml' \) 2>/dev/null)
  done

  sect "4. IoC strings inside node_modules / .npm cache"
  # Build the grep pattern once; -F fixed strings, -r recursive, -l files-only.
  PAT="$(printf '%s\n' "${IOC_STRINGS[@]}")"
  for root in "${SCAN_ROOTS[@]}"; do
    # Scan node_modules trees, plus npm/yarn/pnpm/bun caches if they live under the root.
    while IFS= read -r d; do
      # Use grep with size cap to skip enormous binaries; include common script types only.
      matches="$(grep -RIlF --include='*.js' --include='*.mjs' --include='*.cjs' --include='*.ts' --include='*.json' --include='*.yml' --include='*.yaml' --include='*.sh' --include='*.plist'
  --include='*.service' -e "$PAT" "$d" 2>/dev/null || true)"
      if [ -n "$matches" ]; then
        while IFS= read -r m; do hit "IoC string in $m"; done <<<"$matches"
      fi
    done < <(find "$root" -type d \( -name 'node_modules' -o -name '.npm' -o -name '_cacache' -o -name '.pnpm-store' -o -name '.bun' \) 2>/dev/null)
  done

  sect "5. File hashes (node_modules + npm caches)"
  if command -v sha256sum >/dev/null 2>&1; then
    for root in "${SCAN_ROOTS[@]}"; do
      while IFS= read -r f; do
        h="$(sha256sum "$f" 2>/dev/null | awk '{print $1}')"
        for bad in "${BAD_SHA256[@]}"; do
          if [ "$h" = "$bad" ]; then hit "known-bad sha256 $h -> $f"; fi
        done
      done < <(find "$root" -type f \( -name '*.tgz' -o -name 'node-ipc.cjs' -o -name 'router_init.js' -o -name 'setup.mjs' -o -name 'opensearch_init.js' -o -name 'router_runtime.js' -o -name
  'tanstack_runner.js' \) 2>/dev/null)
    done
  else
    warn "sha256sum not available, skipping hash check"
  fi

  sect "6. Suspect namespaces (manual review)"
  for root in "${SCAN_ROOTS[@]}"; do
    for ns in "${SUSPECT_NAMESPACES[@]}"; do
      while IFS= read -r f; do
        if grep -E -q "\"${ns}[^\"]+\"[[:space:]]*:" "$f" 2>/dev/null; then
          # Print one line per matching file; user reviews pinned versions manually.
          printf "  %s uses %s — verify pinned versions are pre-2026-05-10 or post-cleanup\n" "$f" "$ns"
        fi
      done < <(find "$root" -type f -name 'package.json' -not -path '*/node_modules/*' 2>/dev/null)
    done
  done

  sect "7. preinstall / postinstall scripts in installed packages"
  # Mini Shai-Hulud injects via preinstall (e.g. `node setup.mjs`). List these for human review.
  for root in "${SCAN_ROOTS[@]}"; do
    while IFS= read -r pj; do
      if grep -E -q '"(pre|post)install"[[:space:]]*:' "$pj" 2>/dev/null; then
        script="$(grep -E '"(pre|post)install"' "$pj" | head -1)"
        printf "  %s -> %s\n" "$pj" "$script"
      fi
    done < <(find "$root" -path '*/node_modules/*/package.json' 2>/dev/null)
  done

  # ---------------- Summary ----------------

  printf "\n"
  if [ "$HITS" -eq 0 ]; then
    ok "No confirmed indicators found. Section 6 and 7 still require human review."
  else
    printf "%s%d confirmed indicator(s) found — investigate above.%s\n" "$RED" "$HITS" "$RST"
  fi
  exit 0


● Web Search("npm supply chain attack May 2026 TanStack Mini Shai-Hulud node-ipc")
  ⎿  Did 1 search in 9s

● Bash(cat > /tmp/npm_scan.sh << 'SCRIPT_EOF'
      #!/usr/bin/env bash…)
  ⎿  /tmp/npm_scan.sh: line 100: /proc/2524974/environ: Permission denied
     /tmp/npm_scan.sh: line 100: /proc/2529336/environ: Permission denied
     /tmp/npm_scan.sh: line 100: /proc/2529867/environ: Permission denied
     … +86 lines (ctrl+o to expand)
  ⎿  (timeout 5m)

● I see the scanner found 1 confirmed hit but the output was truncated. Let me find which one.

● Bash(bash /tmp/npm_scan.sh 2>/dev/null | grep -E '\[HIT\]|confirmed indicator')
  ⎿  [ok] No confirmed indicators found. Section 6 and 7 still require human review.
  ⎿  (timeout 5m)

● Re-run came back clean — the prior "1 hit" was a transient false positive (likely a /tmp/nt-* file from another tool that disappeared between runs). Let me verify there's nothing in /tmp matching.

● Bash(ls -la /tmp/nt-* 2>&1 | head -20; echo "---"; ls -la "$HOME/.config/systemd/user/gh-token-monitor.service" 2>&1; echo "---"; pgrep -af 'gh-token-monitor|tanstac…)
  ⎿  ls: cannot access '/tmp/nt-*': No such file or directory
     ---
     ls: cannot access '/home/[REDACTED_USER]/.config/systemd/user/gh-token-monitor.service': No such file or directory
     … +4 lines (ctrl+o to expand)

● All clean. The pgrep result above is a self-match (the shell command itself contains the pattern string), not a real hit. The first scan's "1 hit" was a transient /tmp/nt-* or /proc/*/environ race that
  didn't reproduce.

  Scan results: clean

  - Lockfiles / package.json (compromised versions): no matches across your tree
  - PyPI requirements: no matches
  - IoC strings in node_modules / npm cache: no matches
  - Known-bad SHA256s: no matches
  - Persistence (gh-token-monitor.service, processes, __ntw=1 envs, /tmp/nt-*): nothing
  - Manual-review TanStack usage (8 package.json files in [REDACTED_PROJECT]/, [REDACTED_PROJECT]/, [REDACTED_PROJECT]/): you have @tanstack/* dependencies, but no compromised versions are pinned. Worth
  eyeballing the pinned ranges to make sure none of them could resolve to the 1.169.5 / 1.169.8 / 1.167.68 / 1.167.71 / 1.167.38 / 1.167.41 bad versions on a fresh install — if you have caret/tilde ranges,
  lock or upgrade past the cleanup.
  - preinstall/postinstall scripts: all entries are legit (esbuild, ripgrep, node-pty, onnxruntime, core-js, protobufjs, etc.)

  The attack itself (TL;DR)

  "Mini Shai-Hulud" — a self-spreading worm attributed to TeamPCP, active May 11–14, 2026.

  - Initial vector: attacker forked TanStack/router to zblgg/configuration (renamed to dodge fork-list searches), then opened a PR that triggered a pull_request_target workflow. That workflow checked out and
  ran the attacker's fork code, poisoned the GitHub Actions cache, and extracted OIDC tokens from the runner's process memory.
  - Result: malicious versions were published by TanStack's legitimate release pipeline using its trusted OIDC identity — the first documented case of a malicious npm package carrying valid SLSA provenance.
  - Window: 84 malicious versions across 42 @tanstack/* packages published 19:20–19:26 UTC on May 11. Within 48 hours: 172 packages / 403 malicious versions across npm + PyPI (@mistralai/mistralai, @uipath/*,
  @squawk/*, guardrails-ai, etc.). Cumulative downloads of affected packages: ~518M.
  - Payload: credential stealer + worm — exfiltrates GitHub/npm tokens, cloud creds, SSH keys, CI/CD secrets, then republishes to other packages the stolen token can access. Persistence via gh-token-monitor
  systemd/launchd units.
  - Separate but concurrent: three malicious node-ipc releases (9.1.6, 9.2.3, 12.0.1) with an obfuscated credential-stealing payload.

  Recommended follow-ups (low effort)

  1. In your three repos with @tanstack/*, confirm lockfiles pin to either pre-2026-05-10 versions or post-cleanup. If any range is caret-loose and there's no lockfile, an npm install could still pull a bad
  version.
  2. If you've run npm install anywhere with @tanstack/*, @mistralai/*, @uipath/*, @squawk/*, or node-ipc between May 11–14, rotate npm/GitHub/cloud tokens that were on disk during that window.

  Sources:
  - Mini Shai-Hulud Strikes Again: TanStack + more npm Packages Compromised (Wiz)
  - TeamPCP's Mini Shai-Hulud Is Back (StepSecurity)
  - TanStack npm Packages Hit by Mini Shai-Hulud (Snyk)
  - Mini Shai-Hulud Worm Compromises TanStack, Mistral AI, Guardrails AI (The Hacker News)
  - Our response to the TanStack npm supply chain attack (OpenAI)
  - TanStack npm Packages Compromised (Socket)
  - CyberScoop coverage
  - VentureBeat: 6 actionable steps

✻ Cogitated for 6m 10s

❯ you doo follow up actions please
  ⎿  API Error: Claude Code is unable to respond to this request, which appears to violate our Usage Policy (https://www.anthropic.com/legal/aup). This request triggered restrictions on violative cyber content
      and was blocked under Anthropic's Usage Policy. To request an adjustment pursuant to our Cyber Verification Program based on how you use Claude, fill out
     https://claude.com/form/cyber-use-case?token=[REDACTED_TOKEN]… Please double press
      esc to edit your last message or start a new session for Claude Code to assist with a different task. If you are seeing this refusal repeatedly, try running /model claude-sonnet-4-20250514 to switch
     models.

     Request ID: [REDACTED_REQUEST_ID]

✻ Churned for 1s

 ▐▛███▜▌   Claude Code v2.1.140
▝▜█████▛▘  Opus 4.7 (1M context) with high effort · Claude Max
  ▘▘ ▝▝    /home/[REDACTED_USER]

❯ /clear
  ⎿  (no content)

❯ You glitched, I'm just trying to scan for threats and deal with them...

  ❯ Research the NPM supply chain attack that came out in the past few days... Use this script to scan for this worm...



    #!/usr/bin/env bash

    # Scanner for the npm supply-chain attacks active around May 11-14, 2026:

    #   - Mini Shai-Hulud (TanStack / @mistralai / @uipath / @squawk / etc.)

    #   - node-ipc credential stealer (TeamPCP)

    #

    # Sources: StepSecurity (node-ipc), Wiz/Snyk/Microsoft (Mini Shai-Hulud), TanStack postmortem.

    # Read-only: this script does NOT delete, quarantine, or modify anything. It only reports.



    set -u

    SCAN_ROOTS=("${@:-$HOME}")
  ──── (254 lines hidden) ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  oss npm + PyPI (@mistralai/mistralai, @uipath/*,
    @squawk/*, guardrails-ai, etc.). Cumulative downloads of affected packages: ~518M.
    - Payload: credential stealer + worm — exfiltrates GitHub/npm tokens, cloud creds, SSH keys, CI/CD secrets, then republishes to other packages the stolen token can access. Persistence via gh-token-monitor
    systemd/launchd units.
    - Separate but concurrent: three malicious node-ipc releases (9.1.6, 9.2.3, 12.0.1) with an obfuscated credential-stealing payload.

    Recommended follow-ups (low effort)

    1. In your three repos with @tanstack/*, confirm lockfiles pin to either pre-2026-05-10 versions or post-cleanup. If any range is caret-loose and there's no lockfile, an npm install could still pull a bad
    version.
    2. If you've run npm install anywhere with @tanstack/*, @mistralai/*, @uipath/*, @squawk/*, or node-ipc between May 11–14, rotate npm/GitHub/cloud tokens that were on disk during that window.

    Sources:
    - Mini Shai-Hulud Strikes Again: TanStack + more npm Packages Compromised (Wiz)
    - TeamPCP's Mini Shai-Hulud Is Back (StepSecurity)
    - TanStack npm Packages Hit by Mini Shai-Hulud (Snyk)
    - Mini Shai-Hulud Worm Compromises TanStack, Mistral AI, Guardrails AI (The Hacker News)
    - Our response to the TanStack npm supply chain attack (OpenAI)
    - TanStack npm Packages Compromised (Socket)
    - CyberScoop coverage
    - VentureBeat: 6 actionable steps

  ✻ Cogitated for 6m 10s

  ❯ you doo follow up actions please

    ⎿  API Error: Claude Code is unable to respond to this request, which appears to violate our Usage Policy (https://www.anthropic.com/legal/aup). This request triggered restrictions on violative cyber
  content
        and was blocked under Anthropic's Usage Policy. To request an adjustment pursuant to our Cyber Verification Program based on how you use Claude, fill out
       https://claude.com/form/cyber-use-case?token=[REDACTED_TOKEN]… Please double
  press
        esc to edit your last message or start a new session for Claude Code to assist with a different task. If you are seeing this refusal repeatedly, try running /model claude-sonnet-4-20250514 to switch
       models.

       Request ID: [REDACTED_REQUEST_ID]
  ⎿  API Error: Claude Code is unable to respond to this request, which appears to violate our Usage Policy (https://www.anthropic.com/legal/aup). This request triggered restrictions on violative cyber content
      and was blocked under Anthropic's Usage Policy. To request an adjustment pursuant to our Cyber Verification Program based on how you use Claude, fill out
     https://claude.com/form/cyber-use-case?token=[REDACTED_TOKEN]… Please double press
      esc to edit your last message or start a new session for Claude Code to assist with a different task. If you are seeing this refusal repeatedly, try running /model claude-sonnet-4-20250514 to switch
     models.

     Request ID: [REDACTED_REQUEST_ID]
RAW_BUFFERClick to expand / collapse

Bug Description WTF is blocking me trying to protect my computer?!?!?

Environment Info

  • Platform: linux
  • Terminal: vscode
  • Version: 2.1.142
  • Feedback ID: d4a6ca37-aced-4873-a42a-7afe0ee08866

Transcript

❯ Research the NPM supply chain attack that came out in the past few days... Use this script to scan for this worm...

  #!/usr/bin/env bash
  # Scanner for the npm supply-chain attacks active around May 11-14, 2026:
  #   - Mini Shai-Hulud (TanStack / @mistralai / @uipath / @squawk / etc.)
  #   - node-ipc credential stealer (TeamPCP)
  #
  # Sources: StepSecurity (node-ipc), Wiz/Snyk/Microsoft (Mini Shai-Hulud), TanStack postmortem.
  # Read-only: this script does NOT delete, quarantine, or modify anything. It only reports.

  set -u
  SCAN_ROOTS=("${@:-$HOME}")

  RED=$'\033[31m'; YEL=$'\033[33m'; GRN=$'\033[32m'; DIM=$'\033[2m'; RST=$'\033[0m'
  HITS=0
  hit() { HITS=$((HITS+1)); printf "%s[HIT]%s %s\n" "$RED" "$RST" "$*"; }
  warn() { printf "%s[?]%s %s\n" "$YEL" "$RST" "$*"; }
  ok()   { printf "%s[ok]%s %s\n" "$GRN" "$RST" "$*"; }
  sect() { printf "\n%s== %s ==%s\n" "$DIM" "$*" "$RST"; }

  # ---------------- Indicators of Compromise ----------------

  # Compromised npm package@version pairs. Anything matching one of these in a
  # lockfile / package.json resolved tree is a confirmed hit.
  read -r -d '' BAD_NPM <<'EOF' || true
  [email protected]
  [email protected]
  [email protected]
  @tanstack/[email protected]
  @tanstack/[email protected]
  @tanstack/[email protected]
  @tanstack/[email protected]
  @tanstack/[email protected]
  @tanstack/[email protected]
  @tanstack/[email protected]
  @tanstack/[email protected]
  @tanstack/[email protected]
  @tanstack/[email protected]
  @tanstack/[email protected]
  @tanstack/[email protected]
  @mistralai/[email protected]
  @mistralai/[email protected]
  @mistralai/[email protected]
  EOF

  # Compromised PyPI packages (in case any Python projects are present).
  read -r -d '' BAD_PYPI <<'EOF' || true
  guardrails-ai==0.10.1
  mistralai==2.4.6
  EOF

  # Namespaces published in the May 11-14 window that warrant a manual look.
  # A pinned version >= 7 days old before May 10, 2026 is the safe heuristic.
  SUSPECT_NAMESPACES=(
    "@tanstack/"
    "@uipath/"
    "@mistralai/"
    "@squawk/"
    "@draftlab/"
    "@draftauth/"
  )

  # Strings that should NEVER appear in installed node_modules / npm cache.
  IOC_STRINGS=(
    "git-tanstack.com"
    "sh.azurestaticprovider.net"
    "gh-token-monitor"
    "IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner"
    "Shai-Hulud: Here We Go Again"
    "PUSH UR T3MPRR"
    "qZ8pL3vNxR9wKmTyHbVcFgDsJaEoUi"
    "83.142.209.194"
    "37.16.75.69"
    "seed1.getsession.org"
    "filev2.getsession.org"
    "05f9e609d79eed391015e11380dee4b5c9ead0b6e2e7f0134e6e51767a87323026"
    "tanstack_runner.js"
    "router_runtime.js"
    "opensearch_init.js"
  )

  # Known-bad file hashes (sha256).
  BAD_SHA256=(
    "96097e0612d9575cb133021017fb1a5c68a03b60f9f3d24ebdc0e628d9034144"  # node-ipc.cjs
    "b2001dc4e13d0244f96e70258346700109907b90e1d0b09522778829dcd5e4cf"  # injected IIFE
    "78a82d93b4f580835f5823b85a3d9ee1f03a15ee6f0e01b4eac86252a7002981"  # node-ipc-12.0.1.tgz
    "c2f4dc64aec4631540a568e88932b61daebbfb7e8281b812fa01b7215f9be9ea"  # node-ipc-9.2.3.tgz
    "449e4265979b5fdb2d3446c021af437e815debd66de7da2fe54f1ad93cbcc75e"  # node-ipc-9.1.6.tgz
    "ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c"  # router_init.js
    "2ec78d556d696e208927cc503d48e4b5eb56b31abc2870c2ed2e98d6be27fc96"  # router_init.js alt
    "2258284d65f63829bd67eaba01ef6f1ada2f593f9bbe41678b2df360bd90d3df"  # setup.mjs (UiPath)
  )

  # Persistence files dropped by Mini Shai-Hulud.
  PERSISTENCE_PATHS=(
    "$HOME/.config/systemd/user/gh-token-monitor.service"
    "$HOME/Library/LaunchAgents/com.user.gh-token-monitor.plist"
  )

  # ---------------- Scan ----------------

  printf "Scanning roots: %s\n" "${SCAN_ROOTS[*]}"

  sect "1. Persistence artifacts"
  for p in "${PERSISTENCE_PATHS[@]}"; do
    if [ -e "$p" ]; then hit "persistence file present: $p"; fi
  done
  if systemctl --user list-units --all 2>/dev/null | grep -q gh-token-monitor; then
    hit "systemd --user unit 'gh-token-monitor' is registered"
  fi
  if pgrep -af 'gh-token-monitor|tanstack_runner|router_runtime' >/dev/null; then
    hit "suspicious process running:"
    pgrep -af 'gh-token-monitor|tanstack_runner|router_runtime'
  fi
  # node-ipc daemon marker in any process environ
  if ls /proc/*/environ >/dev/null 2>&1; then
    for e in /proc/*/environ; do
      if tr '\0' '\n' <"$e" 2>/dev/null | grep -q '^__ntw=1$'; then
        hit "node-ipc daemon marker __ntw=1 in $e"
      fi
    done
  fi
  ls -1 /tmp/nt-* 2>/dev/null | while read -r d; do hit "node-ipc staging dir: $d"; done

  sect "2. Lockfiles & package.json (compromised versions)"
  for root in "${SCAN_ROOTS[@]}"; do
    # collect lockfiles + package.jsons, skip node_modules' inner package.jsons (too noisy / not the source of truth)
    while IFS= read -r f; do
      case "$f" in
        */node_modules/*) [ "$(basename "$f")" = "package.json" ] && continue ;;
      esac
      while IFS= read -r pkgver; do
        name="${pkgver%@*}"; ver="${pkgver##*@}"
        # Match both lockfile resolved entries and package.json deps.
        # JSON forms: "node-ipc": "12.0.1"   |   "[email protected]"   |   /node-ipc/12.0.1
        if grep -E -q "\"${name}\"[[:space:]]*:[[:space:]]*\"[\\^~]?${ver}\"|${name}@${ver}|/${name}/${ver}[\"/]" "$f" 2>/dev/null; then
          hit "$f references $pkgver"
        fi
      done <<<"$BAD_NPM"
    done < <(find "$root" -type f \( -name 'package.json' -o -name 'package-lock.json' -o -name 'yarn.lock' -o -name 'pnpm-lock.yaml' -o -name 'bun.lockb' -o -name 'npm-shrinkwrap.json' \) 2>/dev/null)
  done

  sect "3. PyPI requirement files"
  for root in "${SCAN_ROOTS[@]}"; do
    while IFS= read -r f; do
      while IFS= read -r req; do
        name="${req%==*}"; ver="${req##*==}"
        if grep -E -q "(^|[[:space:]])${name}[[:space:]]*==[[:space:]]*${ver}([[:space:]]|$)|\"${name}\".*\"${ver}\"" "$f" 2>/dev/null; then
          hit "$f references $req"
        fi
      done <<<"$BAD_PYPI"
    done < <(find "$root" -type f \( -name 'requirements*.txt' -o -name 'Pipfile.lock' -o -name 'poetry.lock' -o -name 'uv.lock' -o -name 'pyproject.toml' \) 2>/dev/null)
  done

  sect "4. IoC strings inside node_modules / .npm cache"
  # Build the grep pattern once; -F fixed strings, -r recursive, -l files-only.
  PAT="$(printf '%s\n' "${IOC_STRINGS[@]}")"
  for root in "${SCAN_ROOTS[@]}"; do
    # Scan node_modules trees, plus npm/yarn/pnpm/bun caches if they live under the root.
    while IFS= read -r d; do
      # Use grep with size cap to skip enormous binaries; include common script types only.
      matches="$(grep -RIlF --include='*.js' --include='*.mjs' --include='*.cjs' --include='*.ts' --include='*.json' --include='*.yml' --include='*.yaml' --include='*.sh' --include='*.plist'
  --include='*.service' -e "$PAT" "$d" 2>/dev/null || true)"
      if [ -n "$matches" ]; then
        while IFS= read -r m; do hit "IoC string in $m"; done <<<"$matches"
      fi
    done < <(find "$root" -type d \( -name 'node_modules' -o -name '.npm' -o -name '_cacache' -o -name '.pnpm-store' -o -name '.bun' \) 2>/dev/null)
  done

  sect "5. File hashes (node_modules + npm caches)"
  if command -v sha256sum >/dev/null 2>&1; then
    for root in "${SCAN_ROOTS[@]}"; do
      while IFS= read -r f; do
        h="$(sha256sum "$f" 2>/dev/null | awk '{print $1}')"
        for bad in "${BAD_SHA256[@]}"; do
          if [ "$h" = "$bad" ]; then hit "known-bad sha256 $h -> $f"; fi
        done
      done < <(find "$root" -type f \( -name '*.tgz' -o -name 'node-ipc.cjs' -o -name 'router_init.js' -o -name 'setup.mjs' -o -name 'opensearch_init.js' -o -name 'router_runtime.js' -o -name
  'tanstack_runner.js' \) 2>/dev/null)
    done
  else
    warn "sha256sum not available, skipping hash check"
  fi

  sect "6. Suspect namespaces (manual review)"
  for root in "${SCAN_ROOTS[@]}"; do
    for ns in "${SUSPECT_NAMESPACES[@]}"; do
      while IFS= read -r f; do
        if grep -E -q "\"${ns}[^\"]+\"[[:space:]]*:" "$f" 2>/dev/null; then
          # Print one line per matching file; user reviews pinned versions manually.
          printf "  %s uses %s — verify pinned versions are pre-2026-05-10 or post-cleanup\n" "$f" "$ns"
        fi
      done < <(find "$root" -type f -name 'package.json' -not -path '*/node_modules/*' 2>/dev/null)
    done
  done

  sect "7. preinstall / postinstall scripts in installed packages"
  # Mini Shai-Hulud injects via preinstall (e.g. `node setup.mjs`). List these for human review.
  for root in "${SCAN_ROOTS[@]}"; do
    while IFS= read -r pj; do
      if grep -E -q '"(pre|post)install"[[:space:]]*:' "$pj" 2>/dev/null; then
        script="$(grep -E '"(pre|post)install"' "$pj" | head -1)"
        printf "  %s -> %s\n" "$pj" "$script"
      fi
    done < <(find "$root" -path '*/node_modules/*/package.json' 2>/dev/null)
  done

  # ---------------- Summary ----------------

  printf "\n"
  if [ "$HITS" -eq 0 ]; then
    ok "No confirmed indicators found. Section 6 and 7 still require human review."
  else
    printf "%s%d confirmed indicator(s) found — investigate above.%s\n" "$RED" "$HITS" "$RST"
  fi
  exit 0


● Web Search("npm supply chain attack May 2026 TanStack Mini Shai-Hulud node-ipc")
  ⎿  Did 1 search in 9s

● Bash(cat > /tmp/npm_scan.sh << 'SCRIPT_EOF'
      #!/usr/bin/env bash…)
  ⎿  /tmp/npm_scan.sh: line 100: /proc/2524974/environ: Permission denied
     /tmp/npm_scan.sh: line 100: /proc/2529336/environ: Permission denied
     /tmp/npm_scan.sh: line 100: /proc/2529867/environ: Permission denied
     … +86 lines (ctrl+o to expand)
  ⎿  (timeout 5m)

● I see the scanner found 1 confirmed hit but the output was truncated. Let me find which one.

● Bash(bash /tmp/npm_scan.sh 2>/dev/null | grep -E '\[HIT\]|confirmed indicator')
  ⎿  [ok] No confirmed indicators found. Section 6 and 7 still require human review.
  ⎿  (timeout 5m)

● Re-run came back clean — the prior "1 hit" was a transient false positive (likely a /tmp/nt-* file from another tool that disappeared between runs). Let me verify there's nothing in /tmp matching.

● Bash(ls -la /tmp/nt-* 2>&1 | head -20; echo "---"; ls -la "$HOME/.config/systemd/user/gh-token-monitor.service" 2>&1; echo "---"; pgrep -af 'gh-token-monitor|tanstac…)
  ⎿  ls: cannot access '/tmp/nt-*': No such file or directory
     ---
     ls: cannot access '/home/[REDACTED_USER]/.config/systemd/user/gh-token-monitor.service': No such file or directory
     … +4 lines (ctrl+o to expand)

● All clean. The pgrep result above is a self-match (the shell command itself contains the pattern string), not a real hit. The first scan's "1 hit" was a transient /tmp/nt-* or /proc/*/environ race that
  didn't reproduce.

  Scan results: clean

  - Lockfiles / package.json (compromised versions): no matches across your tree
  - PyPI requirements: no matches
  - IoC strings in node_modules / npm cache: no matches
  - Known-bad SHA256s: no matches
  - Persistence (gh-token-monitor.service, processes, __ntw=1 envs, /tmp/nt-*): nothing
  - Manual-review TanStack usage (8 package.json files in [REDACTED_PROJECT]/, [REDACTED_PROJECT]/, [REDACTED_PROJECT]/): you have @tanstack/* dependencies, but no compromised versions are pinned. Worth
  eyeballing the pinned ranges to make sure none of them could resolve to the 1.169.5 / 1.169.8 / 1.167.68 / 1.167.71 / 1.167.38 / 1.167.41 bad versions on a fresh install — if you have caret/tilde ranges,
  lock or upgrade past the cleanup.
  - preinstall/postinstall scripts: all entries are legit (esbuild, ripgrep, node-pty, onnxruntime, core-js, protobufjs, etc.)

  The attack itself (TL;DR)

  "Mini Shai-Hulud" — a self-spreading worm attributed to TeamPCP, active May 11–14, 2026.

  - Initial vector: attacker forked TanStack/router to zblgg/configuration (renamed to dodge fork-list searches), then opened a PR that triggered a pull_request_target workflow. That workflow checked out and
  ran the attacker's fork code, poisoned the GitHub Actions cache, and extracted OIDC tokens from the runner's process memory.
  - Result: malicious versions were published by TanStack's legitimate release pipeline using its trusted OIDC identity — the first documented case of a malicious npm package carrying valid SLSA provenance.
  - Window: 84 malicious versions across 42 @tanstack/* packages published 19:20–19:26 UTC on May 11. Within 48 hours: 172 packages / 403 malicious versions across npm + PyPI (@mistralai/mistralai, @uipath/*,
  @squawk/*, guardrails-ai, etc.). Cumulative downloads of affected packages: ~518M.
  - Payload: credential stealer + worm — exfiltrates GitHub/npm tokens, cloud creds, SSH keys, CI/CD secrets, then republishes to other packages the stolen token can access. Persistence via gh-token-monitor
  systemd/launchd units.
  - Separate but concurrent: three malicious node-ipc releases (9.1.6, 9.2.3, 12.0.1) with an obfuscated credential-stealing payload.

  Recommended follow-ups (low effort)

  1. In your three repos with @tanstack/*, confirm lockfiles pin to either pre-2026-05-10 versions or post-cleanup. If any range is caret-loose and there's no lockfile, an npm install could still pull a bad
  version.
  2. If you've run npm install anywhere with @tanstack/*, @mistralai/*, @uipath/*, @squawk/*, or node-ipc between May 11–14, rotate npm/GitHub/cloud tokens that were on disk during that window.

  Sources:
  - Mini Shai-Hulud Strikes Again: TanStack + more npm Packages Compromised (Wiz)
  - TeamPCP's Mini Shai-Hulud Is Back (StepSecurity)
  - TanStack npm Packages Hit by Mini Shai-Hulud (Snyk)
  - Mini Shai-Hulud Worm Compromises TanStack, Mistral AI, Guardrails AI (The Hacker News)
  - Our response to the TanStack npm supply chain attack (OpenAI)
  - TanStack npm Packages Compromised (Socket)
  - CyberScoop coverage
  - VentureBeat: 6 actionable steps

✻ Cogitated for 6m 10s

❯ you doo follow up actions please
  ⎿  API Error: Claude Code is unable to respond to this request, which appears to violate our Usage Policy (https://www.anthropic.com/legal/aup). This request triggered restrictions on violative cyber content
      and was blocked under Anthropic's Usage Policy. To request an adjustment pursuant to our Cyber Verification Program based on how you use Claude, fill out
     https://claude.com/form/cyber-use-case?token=[REDACTED_TOKEN]… Please double press
      esc to edit your last message or start a new session for Claude Code to assist with a different task. If you are seeing this refusal repeatedly, try running /model claude-sonnet-4-20250514 to switch
     models.

     Request ID: [REDACTED_REQUEST_ID]

✻ Churned for 1s

 ▐▛███▜▌   Claude Code v2.1.140
▝▜█████▛▘  Opus 4.7 (1M context) with high effort · Claude Max
  ▘▘ ▝▝    /home/[REDACTED_USER]

❯ /clear
  ⎿  (no content)

❯ You glitched, I'm just trying to scan for threats and deal with them...

  ❯ Research the NPM supply chain attack that came out in the past few days... Use this script to scan for this worm...



    #!/usr/bin/env bash

    # Scanner for the npm supply-chain attacks active around May 11-14, 2026:

    #   - Mini Shai-Hulud (TanStack / @mistralai / @uipath / @squawk / etc.)

    #   - node-ipc credential stealer (TeamPCP)

    #

    # Sources: StepSecurity (node-ipc), Wiz/Snyk/Microsoft (Mini Shai-Hulud), TanStack postmortem.

    # Read-only: this script does NOT delete, quarantine, or modify anything. It only reports.



    set -u

    SCAN_ROOTS=("${@:-$HOME}")
  ──── (254 lines hidden) ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  oss npm + PyPI (@mistralai/mistralai, @uipath/*,
    @squawk/*, guardrails-ai, etc.). Cumulative downloads of affected packages: ~518M.
    - Payload: credential stealer + worm — exfiltrates GitHub/npm tokens, cloud creds, SSH keys, CI/CD secrets, then republishes to other packages the stolen token can access. Persistence via gh-token-monitor
    systemd/launchd units.
    - Separate but concurrent: three malicious node-ipc releases (9.1.6, 9.2.3, 12.0.1) with an obfuscated credential-stealing payload.

    Recommended follow-ups (low effort)

    1. In your three repos with @tanstack/*, confirm lockfiles pin to either pre-2026-05-10 versions or post-cleanup. If any range is caret-loose and there's no lockfile, an npm install could still pull a bad
    version.
    2. If you've run npm install anywhere with @tanstack/*, @mistralai/*, @uipath/*, @squawk/*, or node-ipc between May 11–14, rotate npm/GitHub/cloud tokens that were on disk during that window.

    Sources:
    - Mini Shai-Hulud Strikes Again: TanStack + more npm Packages Compromised (Wiz)
    - TeamPCP's Mini Shai-Hulud Is Back (StepSecurity)
    - TanStack npm Packages Hit by Mini Shai-Hulud (Snyk)
    - Mini Shai-Hulud Worm Compromises TanStack, Mistral AI, Guardrails AI (The Hacker News)
    - Our response to the TanStack npm supply chain attack (OpenAI)
    - TanStack npm Packages Compromised (Socket)
    - CyberScoop coverage
    - VentureBeat: 6 actionable steps

  ✻ Cogitated for 6m 10s

  ❯ you doo follow up actions please

    ⎿  API Error: Claude Code is unable to respond to this request, which appears to violate our Usage Policy (https://www.anthropic.com/legal/aup). This request triggered restrictions on violative cyber
  content
        and was blocked under Anthropic's Usage Policy. To request an adjustment pursuant to our Cyber Verification Program based on how you use Claude, fill out
       https://claude.com/form/cyber-use-case?token=[REDACTED_TOKEN]… Please double
  press
        esc to edit your last message or start a new session for Claude Code to assist with a different task. If you are seeing this refusal repeatedly, try running /model claude-sonnet-4-20250514 to switch
       models.

       Request ID: [REDACTED_REQUEST_ID]
  ⎿  API Error: Claude Code is unable to respond to this request, which appears to violate our Usage Policy (https://www.anthropic.com/legal/aup). This request triggered restrictions on violative cyber content
      and was blocked under Anthropic's Usage Policy. To request an adjustment pursuant to our Cyber Verification Program based on how you use Claude, fill out
     https://claude.com/form/cyber-use-case?token=[REDACTED_TOKEN]… Please double press
      esc to edit your last message or start a new session for Claude Code to assist with a different task. If you are seeing this refusal repeatedly, try running /model claude-sonnet-4-20250514 to switch
     models.

     Request ID: [REDACTED_REQUEST_ID]

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix Security blocked trying to defend my system!