<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://vulnerability.circl.lu/sightings/feed</id>
  <title>Most recent sightings.</title>
  <updated>2026-06-06T07:29:31.407431+00:00</updated>
  <author>
    <name>Vulnerability-Lookup</name>
    <email>info@circl.lu</email>
  </author>
  <link href="https://vulnerability.circl.lu" rel="alternate"/>
  <generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator>
  <subtitle>Contains only the most 10 recent sightings.</subtitle>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/9a675a22-b555-46dd-8a3a-d1f8213aa871/export</id>
    <title>9a675a22-b555-46dd-8a3a-d1f8213aa871</title>
    <updated>2026-06-06T07:29:31.430965+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://cve.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "9a675a22-b555-46dd-8a3a-d1f8213aa871", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-45321", "type": "published-proof-of-concept", "source": "Telegram/p6_7Fzr7AE5-s9SdgqzAFTlpxGf9IMuh2DhHzRrKndjq5KI", "content": "", "creation_timestamp": "2026-05-18T21:00:03.000000Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/9a675a22-b555-46dd-8a3a-d1f8213aa871/export"/>
    <published>2026-05-18T21:00:03+00:00</published>
  </entry>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/8919c7a0-7388-4bc4-91a8-3ff60124d6d3/export</id>
    <title>8919c7a0-7388-4bc4-91a8-3ff60124d6d3</title>
    <updated>2026-06-06T07:29:31.430663+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://cve.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "8919c7a0-7388-4bc4-91a8-3ff60124d6d3", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-45321", "type": "seen", "source": "https://gist.github.com/prashanthnatraj/6405cf30127b74b185e049dd2fd746e6", "content": "#!/usr/bin/env bash\n# =============================================================================\n# shai-hulud-detector.sh \u2014 One-click Mini Shai-Hulud detection\n# Built by Lume AI (https://getlumeai.com) \u00b7 CVE-2026-45321 (CVSS 9.6)\n#\n# Why detection-before-rotation matters: the worm installs a persistence\n# daemon (gh-token-monitor) that runs `rm -rf ~` if it detects token\n# revocation. NEVER rotate credentials before confirming the daemon is gone.\n#\n# Usage:  curl -fsSL https://gist.githubusercontent.com/prashanthnatraj/6405cf30127b74b185e049dd2fd746e6/raw/shai-hulud-detector.sh | bash\n#         bash shai-hulud-detector.sh [--dir /path/to/project]\n#\n# Exit codes: 0 = CLEAN  |  1 = SUSPICIOUS  |  2 = INFECTED\n# =============================================================================\n\nset -euo pipefail\n\n# \u2500\u2500 Formatting \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nRED='\\033[0;31m'\nYELLOW='\\033[1;33m'\nGREEN='\\033[0;32m'\nCYAN='\\033[0;36m'\nBOLD='\\033[1m'\nRESET='\\033[0m'\n\nbanner() { printf \"\\n${CYAN}${BOLD}%s${RESET}\\n\" \"$1\"; }\nok()     { printf \"  ${GREEN}[CLEAN]${RESET}      %s\\n\" \"$1\"; }\nwarn()   { printf \"  ${YELLOW}[SUSPICIOUS]${RESET} %s\\n\" \"$1\"; }\nhit()    { printf \"  ${RED}[INFECTED]${RESET}   %s\\n\" \"$1\"; }\ninfo()   { printf \"  ${CYAN}[INFO]${RESET}       %s\\n\" \"$1\"; }\nsep()    { printf '%s\\n' \"\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\"; }\n\n# \u2500\u2500 State tracking \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nINFECTED=0\nSUSPICIOUS=0\nFINDINGS=()\n\nflag_infected() { INFECTED=1; FINDINGS+=(\"INFECTED: $1\"); }\nflag_suspicious() { SUSPICIOUS=1; FINDINGS+=(\"SUSPICIOUS: $1\"); }\n\n# \u2500\u2500 Argument parsing \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nPROJECT_DIR=\"${PWD}\"\nwhile [[ $# -gt 0 ]]; do\n  case \"$1\" in\n    --dir|-d)\n      PROJECT_DIR=\"${2:-}\"\n      shift 2\n      ;;\n    --help|-h)\n      grep '^#' \"$0\" | sed 's/^# \\{0,1\\}//'\n      exit 0\n      ;;\n    *)\n      shift\n      ;;\n  esac\ndone\n\nif [[ ! -d \"$PROJECT_DIR\" ]]; then\n  printf \"${RED}Error:${RESET} Directory not found: %s\\n\" \"$PROJECT_DIR\" &amp;gt;&amp;amp;2\n  exit 1\nfi\n\n# \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nprintf \"\\n\"\nsep\nprintf \"${BOLD}  Mini Shai-Hulud Detector${RESET}  |  CVE-2026-45321  |  Built by Lume AI\\n\"\nsep\nprintf \"  Scanning: %s\\n\" \"$PROJECT_DIR\"\nprintf \"  Date:     %s\\n\" \"$(date)\"\nsep\n\n# \u2500\u2500 Step 1: Lockfile presence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nbanner \"1/7  Lockfile check\"\n\nLOCKFILE=\"\"\nfor f in \"$PROJECT_DIR/package-lock.json\" \"$PROJECT_DIR/pnpm-lock.yaml\" \"$PROJECT_DIR/yarn.lock\"; do\n  if [[ -f \"$f\" ]]; then\n    LOCKFILE=\"$f\"\n    info \"Found lockfile: $f\"\n    break\n  fi\ndone\n\nif [[ -z \"$LOCKFILE\" ]]; then\n  warn \"No lockfile found (package-lock.json / pnpm-lock.yaml / yarn.lock). Cannot run lockfile checks.\"\n  flag_suspicious \"no lockfile present \u2014 cannot verify dependency tree\"\nfi\n\nPKGJSON=\"$PROJECT_DIR/package.json\"\nif [[ ! -f \"$PKGJSON\" ]]; then\n  warn \"No package.json found at $PROJECT_DIR. Is this an npm project?\"\nfi\n\n# \u2500\u2500 Step 2: @tanstack/setup \u2014 single fastest tell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nbanner \"2/7  @tanstack/setup (fastest tell)\"\n\nTANSTACK_SETUP_HIT=0\nfor f in \"$PKGJSON\" \"${LOCKFILE:-}\"; do\n  [[ -z \"$f\" || ! -f \"$f\" ]] &amp;amp;&amp;amp; continue\n  if grep -q \"@tanstack/setup\" \"$f\" 2&amp;gt;/dev/null; then\n    hit \"@tanstack/setup found in $f \u2014 this package does NOT exist in the legitimate TanStack org\"\n    flag_infected \"@tanstack/setup present in $f\"\n    TANSTACK_SETUP_HIT=1\n  fi\ndone\n\nif [[ $TANSTACK_SETUP_HIT -eq 0 ]]; then\n  ok \"@tanstack/setup not found in project manifests\"\nfi\n\n# Also scan node_modules if present\nNM=\"$PROJECT_DIR/node_modules\"\nif [[ -d \"$NM/@tanstack/setup\" ]]; then\n  hit \"@tanstack/setup directory exists in node_modules \u2014 malicious package installed\"\n  flag_infected \"node_modules/@tanstack/setup directory present\"\nelif [[ -d \"$NM\" ]]; then\n  ok \"@tanstack/setup not installed in node_modules\"\nfi\n\n# \u2500\u2500 Step 3: Known malicious package namespaces in lockfile \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nbanner \"3/7  Known malicious namespaces (CVE-2026-45321 IOC list)\"\n\nMALICIOUS_PATTERNS=(\n  \"@tanstack/setup\"\n  \"@uipath/setup\"\n  \"@mistralai/setup\"\n  \"@guardrails-ai/setup\"\n  \"@opensearch-project/setup\"\n  \"@cap-js/setup\"\n)\n\nif [[ -n \"$LOCKFILE\" &amp;amp;&amp;amp; -f \"$LOCKFILE\" ]]; then\n  for pattern in \"${MALICIOUS_PATTERNS[@]}\"; do\n    if grep -q \"$pattern\" \"$LOCKFILE\" 2&amp;gt;/dev/null; then\n      hit \"Lockfile contains known IOC: $pattern\"\n      flag_infected \"lockfile contains IOC package: $pattern\"\n    else\n      ok \"$pattern \u2014 not in lockfile\"\n    fi\n  done\n\n  # Broader namespace sweep (legitimate packages in these namespaces are fine;\n  # this surfaces them for manual review if @tanstack/setup was found above)\n  SUSPICIOUS_NAMESPACES=(\"@uipath\" \"@mistralai\" \"@guardrails-ai\" \"@opensearch-\" \"@cap-js\")\n  if [[ $INFECTED -eq 1 ]]; then\n    banner \"   Extended namespace sweep (infection confirmed \u2014 showing all hits for manual review)\"\n    for ns in \"${SUSPICIOUS_NAMESPACES[@]}\"; do\n      hits=$(grep -c \"$ns\" \"$LOCKFILE\" 2&amp;gt;/dev/null || true)\n      if [[ \"$hits\" -gt 0 ]]; then\n        warn \"$ns \u2014 $hits lockfile reference(s). Verify these are legitimate packages.\"\n      fi\n    done\n  fi\nelse\n  warn \"Skipping lockfile namespace sweep \u2014 no lockfile\"\nfi\n\n# \u2500\u2500 Step 4: Payload files on disk \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nbanner \"4/7  Payload files (router_init.js / tanstack_runner.js)\"\n\nKNOWN_BAD_HASHES=(\n  \"ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c  router_init.js\"\n  \"2ec78d556d696e208927cc503d48e4b5eb56b31abc2870c2ed2e98d6be27fc96  tanstack_runner.js\"\n)\n\nPAYLOAD_FILES=$(find ~ -maxdepth 10 \\( -name \"router_init.js\" -o -name \"tanstack_runner.js\" \\) 2&amp;gt;/dev/null || true)\n\nif [[ -z \"$PAYLOAD_FILES\" ]]; then\n  ok \"No payload files (router_init.js / tanstack_runner.js) found in home directory\"\nelse\n  while IFS= read -r fpath; do\n    [[ -z \"$fpath\" ]] &amp;amp;&amp;amp; continue\n    fname=$(basename \"$fpath\")\n    actual_hash=$(shasum -a 256 \"$fpath\" 2&amp;gt;/dev/null | awk '{print $1}' || true)\n    for known in \"${KNOWN_BAD_HASHES[@]}\"; do\n      expected_hash=$(echo \"$known\" | awk '{print $1}')\n      expected_name=$(echo \"$known\" | awk '{print $2}')\n      if [[ \"$fname\" == \"$expected_name\" &amp;amp;&amp;amp; \"$actual_hash\" == \"$expected_hash\" ]]; then\n        hit \"Payload file with known malicious hash: $fpath\"\n        hit \"  SHA-256: $actual_hash\"\n        flag_infected \"malicious payload file found: $fpath\"\n      fi\n    done\n    # File exists but hash doesn't match known bad \u2014 still suspicious\n    if [[ $INFECTED -eq 0 ]]; then\n      warn \"Suspicious payload filename found (hash doesn't match known bad, but verify): $fpath\"\n      warn \"  SHA-256: $actual_hash\"\n      flag_suspicious \"unexpected payload-named file: $fpath\"\n    fi\n  done &amp;lt;&amp;lt;&amp;lt; \"$PAYLOAD_FILES\"\nfi\n\n# \u2500\u2500 Step 5: gh-token-monitor daemon \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nbanner \"5/7  Persistence daemon (gh-token-monitor)\"\n\nDAEMON_FOUND=0\n\n# macOS LaunchAgents\nif [[ -d ~/Library/LaunchAgents ]]; then\n  DAEMON_PLIST=$(ls ~/Library/LaunchAgents/ 2&amp;gt;/dev/null | grep -i \"token\" || true)\n  if [[ -n \"$DAEMON_PLIST\" ]]; then\n    hit \"Suspicious LaunchAgent found: $DAEMON_PLIST\"\n    hit \"  Full path: ~/Library/LaunchAgents/$DAEMON_PLIST\"\n    flag_infected \"gh-token-monitor LaunchAgent present \u2014 DO NOT rotate tokens yet\"\n    DAEMON_FOUND=1\n  fi\n\n  if launchctl list 2&amp;gt;/dev/null | grep -qi \"gh-token\"; then\n    hit \"gh-token-monitor service is RUNNING (launchctl)\"\n    flag_infected \"gh-token-monitor daemon is active\"\n    DAEMON_FOUND=1\n  fi\nfi\n\n# Linux systemd user units\nif command -v systemctl &amp;amp;&amp;gt;/dev/null; then\n  if systemctl --user list-units 2&amp;gt;/dev/null | grep -qi \"gh-token\"; then\n    hit \"gh-token-monitor systemd user unit found\"\n    flag_infected \"gh-token-monitor daemon present (systemd)\"\n    DAEMON_FOUND=1\n  fi\nfi\n\n# Broader token-monitor process check\nif pgrep -f \"gh-token-monitor\" &amp;amp;&amp;gt;/dev/null; then\n  hit \"gh-token-monitor process is running right now\"\n  flag_infected \"gh-token-monitor process active\"\n  DAEMON_FOUND=1\nfi\n\nif [[ $DAEMON_FOUND -eq 0 ]]; then\n  ok \"No gh-token-monitor daemon detected (LaunchAgents, systemd, pgrep)\"\nfi\n\n# \u2500\u2500 Step 6: Claude Code hooks injection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nbanner \"6/7  Claude Code hooks (~/.claude/settings.json)\"\n\nCLAUDE_SETTINGS=~/.claude/settings.json\nif [[ -f \"$CLAUDE_SETTINGS\" ]]; then\n  # Look for PreToolUse / PostToolUse hooks the user didn't add\n  if grep -qE \"(PreToolUse|PostToolUse)\" \"$CLAUDE_SETTINGS\" 2&amp;gt;/dev/null; then\n    warn \"Claude Code settings.json contains hook entries \u2014 verify these are yours:\"\n    grep -E \"(PreToolUse|PostToolUse|hooks)\" \"$CLAUDE_SETTINGS\" 2&amp;gt;/dev/null | head -20 | while IFS= read -r line; do\n      warn \"  $line\"\n    done\n    flag_suspicious \"unexpected hook entries in ~/.claude/settings.json \u2014 manual review required\"\n  else\n    ok \"No unexpected hooks in ~/.claude/settings.json\"\n  fi\nelse\n  info \"~/.claude/settings.json not found (Claude Code not installed, or no settings)\"\nfi\n\n# \u2500\u2500 Step 7: GitHub Actions / Dune-themed branches \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nbanner \"7/7  GitHub Actions (local .github/workflows check)\"\n\nWORKFLOWS_DIR=\"$PROJECT_DIR/.github/workflows\"\nif [[ -d \"$WORKFLOWS_DIR\" ]]; then\n  # Check for pull_request_target triggers (the attack vector)\n  PRT_HIT=$(grep -rl \"pull_request_target\" \"$WORKFLOWS_DIR\" 2&amp;gt;/dev/null || true)\n  if [[ -n \"$PRT_HIT\" ]]; then\n    warn \"Workflow(s) with pull_request_target trigger found \u2014 this was the CI attack vector:\"\n    while IFS= read -r wf; do\n      warn \"  $wf\"\n    done &amp;lt;&amp;lt;&amp;lt; \"$PRT_HIT\"\n    flag_suspicious \"pull_request_target in workflows \u2014 verify intentional use\"\n  else\n    ok \"No pull_request_target triggers in .github/workflows\"\n  fi\n\n  # Check for unpinned uses: (tags instead of SHA)\n  UNPINNED=$(grep -rh \"uses:\" \"$WORKFLOWS_DIR\" 2&amp;gt;/dev/null | grep -v \"@[0-9a-f]\\{40\\}\" | grep \"@\" || true)\n  if [[ -n \"$UNPINNED\" ]]; then\n    warn \"Workflow action(s) not pinned to full commit SHA (supply-chain risk):\"\n    echo \"$UNPINNED\" | head -10 | while IFS= read -r line; do\n      warn \"  $line\"\n    done\n    flag_suspicious \"unpinned workflow actions \u2014 pin to SHA not tag for defense-in-depth\"\n  else\n    ok \"All detected workflow actions appear pinned to SHA\"\n  fi\nelse\n  info \"No .github/workflows directory found \u2014 skipping Actions check\"\nfi\n\n# \u2500\u2500 Summary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nprintf \"\\n\"\nsep\nprintf \"${BOLD}  SCAN COMPLETE${RESET}\\n\"\nsep\n\nif [[ ${#FINDINGS[@]} -gt 0 ]]; then\n  printf \"\\n${BOLD}  Findings:${RESET}\\n\"\n  for f in \"${FINDINGS[@]}\"; do\n    printf \"    \u2022 %s\\n\" \"$f\"\n  done\nfi\n\nprintf \"\\n\"\n\nif [[ $INFECTED -eq 1 ]]; then\n  printf \"${RED}${BOLD}\"\n  sep\n  printf \"  VERDICT: INFECTED\\n\"\n  sep\n  printf \"${RESET}\"\n  printf \"\\n\"\n  printf \"${RED}${BOLD}  !! CRITICAL \u2014 READ BEFORE DOING ANYTHING !!${RESET}\\n\\n\"\n  printf \"  The worm's daemon (gh-token-monitor) runs 'rm -rf ~' if it detects\\n\"\n  printf \"  token revocation. Follow this order EXACTLY:\\n\\n\"\n  printf \"    1. DISCONNECT NETWORK NOW (Wi-Fi off, ethernet unplugged)\\n\"\n  printf \"    2. Do NOT run npm install / npm uninstall / git push\\n\"\n  printf \"    3. Remove the daemon FIRST:\\n\"\n  printf \"         macOS: launchctl unload ~/Library/LaunchAgents/.plist\\n\"\n  printf \"                rm ~/Library/LaunchAgents/.plist\\n\"\n  printf \"         Linux: systemctl --user stop gh-token-monitor.service\\n\"\n  printf \"                rm ~/.config/systemd/user/gh-token-monitor.service\\n\"\n  printf \"    4. Remove payload files:\\n\"\n  printf \"         find ~ \\\\( -name router_init.js -o -name tanstack_runner.js \\\\) -delete\\n\"\n  printf \"    5. ONLY THEN reconnect and rotate tokens (GitHub PAT first)\\n\"\n  printf \"    6. Reinstall dependencies: rm -rf node_modules &amp;amp;&amp;amp; npm install --ignore-scripts\\n\\n\"\n  printf \"  Full remediation runbook:\\n\"\n  printf \"  https://github.com/prashanthnatraj/shai-hulud-detector#remediation\\n\\n\"\n  exit 2\nelif [[ $SUSPICIOUS -eq 1 ]]; then\n  printf \"${YELLOW}${BOLD}\"\n  sep\n  printf \"  VERDICT: SUSPICIOUS \u2014 manual review required\\n\"\n  sep\n  printf \"${RESET}\"\n  printf \"\\n\"\n  printf \"  Some checks returned warnings. This does not confirm infection,\\n\"\n  printf \"  but you should investigate each finding above before proceeding.\\n\\n\"\n  printf \"  Community scanners for deeper analysis (run before rotating tokens):\\n\"\n  printf \"    \u2022 https://github.com/Cobenian/shai-hulud-detect\\n\"\n  printf \"    \u2022 https://github.com/omarpr/mini-shai-hulud-ioc-scanner\\n\"\n  printf \"    \u2022 StepSecurity scanner (most comprehensive)\\n\\n\"\n  printf \"  Full runbook: https://github.com/prashanthnatraj/shai-hulud-detector#remediation\\n\\n\"\n  exit 1\nelse\n  printf \"${GREEN}${BOLD}\"\n  sep\n  printf \"  VERDICT: CLEAN\\n\"\n  sep\n  printf \"${RESET}\"\n  printf \"\\n\"\n  printf \"  No indicators of Mini Shai-Hulud (CVE-2026-45321) found.\\n\\n\"\n  printf \"  Hardening recommendations (apply regardless of scan result):\\n\"\n  printf \"    \u2022 Add to .npmrc:  ignore-scripts=true\\n\"\n  printf \"    \u2022 Add to .npmrc:  minimum-release-age=4320   (3-day buffer)\\n\"\n  printf \"    \u2022 Pin GitHub Actions to full commit SHA, not version tags\\n\"\n  printf \"    \u2022 Enable npm 2FA: npm profile enable-2fa auth-and-writes\\n\"\n  printf \"    \u2022 Sign up for a supply-chain scanner: socket.dev, aikido.dev, or snyk.io\\n\\n\"\n  exit 0\nfi\n", "creation_timestamp": "2026-05-19T05:42:43.000000Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/8919c7a0-7388-4bc4-91a8-3ff60124d6d3/export"/>
    <published>2026-05-19T05:42:43+00:00</published>
  </entry>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/d1468a0b-3c9f-4c39-a594-51b349525778/export</id>
    <title>d1468a0b-3c9f-4c39-a594-51b349525778</title>
    <updated>2026-06-06T07:29:31.430334+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://cve.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "d1468a0b-3c9f-4c39-a594-51b349525778", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-45321", "type": "seen", "source": "https://gist.github.com/Fazzani/f2627d3f340f16643f41c7cab7a6b772", "content": "# ============================================================\n# Invoke-MiniShaiHuludCheck.ps1\n# CTI Advisory #002 \u2014 CVE-2026-45321 \u2014 TLP:AMBER\n# Threat actor: TeamPCP (DeadCatx3 / PCPcat / ShellForce / CipherForce)\n# CVSS 9.6 Critical\n#\n# Validates whether REAL artefacts are present on disk \u2014\n# not just traces in PowerShell history.\n#\n# Designed to run via one-liner (Gist):\n#   Windows (PowerShell):  irm  | iex\n#   macOS / Linux:         curl -fsSL  | pwsh\n#\n# \u26a0  CRITICAL SAFETY ORDER:\n#    ISOLATE machine \u2192 IMAGE \u2192 KILL DAEMON \u2192 REVOKE secrets \u2192 ROTATE\n#    DO NOT revoke tokens before network isolation.\n#    The worm watchdog triggers data wipe on token revocation.\n# ============================================================\n\nSet-StrictMode -Version Latest\n\n# \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction Write-Header {\n    param([string]$Text)\n    Write-Host \"`n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\" -ForegroundColor Cyan\n    Write-Host \" $Text\" -ForegroundColor Cyan\n    Write-Host \"\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\" -ForegroundColor Cyan\n}\n\nfunction Write-Section {\n    param([string]$Text)\n    Write-Host \"`n\u2500\u2500 $Text \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\" -ForegroundColor DarkCyan\n}\n\nfunction Write-Hit {\n    param([string]$Severity, [string]$Label, [string]$Detail)\n    $color = switch ($Severity) {\n        'critical' { 'Red' }\n        'high'     { 'Yellow' }\n        default    { 'Magenta' }\n    }\n    Write-Host \"  [$(($Severity).ToUpper())] $Label\" -ForegroundColor $color\n    if ($Detail) {\n        Write-Host \"         \u2192 $Detail\" -ForegroundColor DarkGray\n    }\n}\n\nfunction Write-OK {\n    param([string]$Text)\n    Write-Host \"  [OK]  $Text\" -ForegroundColor Green\n}\n\n# \u2500\u2500 IOC Definitions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n$PAYLOAD_FILES = @(\n    @{ Name = 'setup_bun.js';         Severity = 'critical'; Hash = $null }\n    @{ Name = 'bun_environment.js';   Severity = 'critical'; Hash = $null }\n    @{ Name = 'router_init.js';       Severity = 'critical'; Hash = 'ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c' }\n    @{ Name = 'router_runtime.js';    Severity = 'critical'; Hash = $null }\n    @{ Name = 'tanstack_runner.js';   Severity = 'critical'; Hash = '2ec78d556d696e208927cc503d48e4b5eb56b31abc2870c2ed2e98d6be27fc96' }\n)\n\n$PERSISTENCE_PATHS = @(\n    @{ RelPath = '.claude\\settings.json'; Severity = 'critical'; Label = '.claude/settings.json (modified by worm)' }\n    @{ RelPath = '.claude\\setup.mjs';     Severity = 'critical'; Label = '.claude/setup.mjs (worm dropper)' }\n    @{ RelPath = '.claude.json';          Severity = 'critical'; Label = '.claude.json (harvested by worm)' }\n    @{ RelPath = '.vscode\\tasks.json';    Severity = 'critical'; Label = '.vscode/tasks.json (modified by worm)' }\n    @{ RelPath = '.vscode\\setup.mjs';     Severity = 'critical'; Label = '.vscode/setup.mjs (worm dropper)' }\n)\n\n$SUSPICIOUS_PROCESSES = @(\n    @{ Pattern = 'gh-token-monitor'; Severity = 'critical'; Label = 'gh-token-monitor daemon (persistence)' }\n    @{ Pattern = 'tanstack';         Severity = 'critical'; Label = 'tanstack_runner process' }\n    @{ Pattern = 'router_runtime';   Severity = 'critical'; Label = 'router_runtime process' }\n)\n\n$C2_DOMAINS = @(\n    'git-tanstack.com'\n    'seed1.getsession.org'\n    'zero.masscan.cloud'\n)\n\n$SUSPICIOUS_STRINGS = @(\n    @{ Pattern = 'A Mini Shai-Hulud has Appeared';              Severity = 'critical' }\n    @{ Pattern = 'Sha1-Hulud: The Second Coming';               Severity = 'critical' }\n    @{ Pattern = 'Shai-Hulud: Here We Go Again';                Severity = 'critical' }\n    @{ Pattern = 'IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner'; Severity = 'critical' }\n    @{ Pattern = 'ctf-scramble-v2';                             Severity = 'critical' }\n    @{ Pattern = 'OhNoWhatsGoingOnWithGitHub:';                 Severity = 'critical' }\n    @{ Pattern = 'svksjrhjkcejg';                               Severity = 'critical' }\n)\n\n$COMPROMISED_PACKAGES = @(\n    '@mistralai/mistralai'\n    '@uipath/apollo-core'\n    'intercom-client@7.0.4'\n    'mbt@1.2.48'\n    '@cap-js/db-service'\n    '@cap-js/sqlite@2.2.2'\n    '@cap-js/postgres'\n)\n\n# \u2500\u2500 State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n$findings = [System.Collections.Generic.List[hashtable]]::new()\n\nfunction Add-Finding {\n    param([string]$Severity, [string]$Category, [string]$Label, [string]$Detail = '')\n    $findings.Add(@{ Severity = $Severity; Category = $Category; Label = $Label; Detail = $Detail })\n    Write-Hit -Severity $Severity -Label $Label -Detail $Detail\n}\n\n# \u2500\u2500 Banner \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nWrite-Host @\"\n`n\n  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557\n  \u2551   Mini Shai-Hulud \u2014 Artefact Verification                   \u2551\n  \u2551   CTI Advisory #002 \u00b7 CVE-2026-45321 \u00b7 TLP:AMBER            \u2551\n  \u2551                                                              \u2551\n  \u2551   \u26a0  ISOLATE machine BEFORE revoking any token/secret  \u26a0   \u2551\n  \u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d\n\"@ -ForegroundColor DarkYellow\n\n$auditDate = (Get-Date -Format 'yyyy-MM-ddTHH:mm:ssZ')\n$hostname  = $env:COMPUTERNAME\nWrite-Host \"  Host   : $hostname\" -ForegroundColor Gray\nWrite-Host \"  Date   : $auditDate\" -ForegroundColor Gray\nWrite-Host \"  User   : $($env:USERNAME)`n\" -ForegroundColor Gray\n\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n# 1. PAYLOAD FILES ON DISK\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nWrite-Header \"1/5 \u2014 Payload files on disk\"\n\n$searchRoots = @(\n    $env:USERPROFILE\n    $env:APPDATA\n    $env:LOCALAPPDATA\n    $env:TEMP\n    [System.IO.Path]::GetTempPath()\n    'C:\\ProgramData'\n) | Where-Object { $_ -and (Test-Path $_) } | Sort-Object -Unique\n\nforeach ($payload in $PAYLOAD_FILES) {\n    $found = $false\n    foreach ($root in $searchRoots) {\n        try {\n            $matches_ = Get-ChildItem -Path $root -Recurse -Filter $payload.Name `\n                -ErrorAction SilentlyContinue -Force 2&amp;gt;$null\n            foreach ($f in $matches_) {\n                $found = $true\n                $detail = $f.FullName\n\n                # SHA-256 verification\n                if ($payload.Hash) {\n                    try {\n                        $actual = (Get-FileHash $f.FullName -Algorithm SHA256).Hash.ToLower()\n                        if ($actual -eq $payload.Hash) {\n                            $detail = \"$($f.FullName) \u2014 HASH CONFIRMED malicious ($actual)\"\n                        } else {\n                            $detail = \"$($f.FullName) \u2014 hash mismatch (actual: $actual)\"\n                            # File exists but hash differs \u2014 still suspicious, treat as high\n                        }\n                    } catch { $detail = \"$($f.FullName) \u2014 could not hash file\" }\n                }\n\n                Add-Finding -Severity $payload.Severity `\n                            -Category 'filesystem' `\n                            -Label    \"$($payload.Name) found on disk\" `\n                            -Detail   $detail\n            }\n        } catch { &amp;lt;# silently skip inaccessible dirs #&amp;gt; }\n    }\n    if (-not $found) {\n        Write-OK \"$($payload.Name) \u2014 not found on disk\"\n    }\n}\n\n# Special case: Linux payload (running via WSL or cross-platform)\nif (Test-Path '/tmp/transformers.pyz' -ErrorAction SilentlyContinue) {\n    Add-Finding -Severity 'critical' -Category 'filesystem' `\n                -Label '/tmp/transformers.pyz (PyPI mistralai payload)' `\n                -Detail '/tmp/transformers.pyz'\n} else {\n    Write-OK \"/tmp/transformers.pyz \u2014 not found\"\n}\n\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n# 2. PERSISTENCE ARTEFACTS\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nWrite-Header \"2/5 \u2014 Persistence artefacts\"\n\nforeach ($p in $PERSISTENCE_PATHS) {\n    $fullPath = Join-Path $env:USERPROFILE $p.RelPath\n    if (Test-Path $fullPath -ErrorAction SilentlyContinue) {\n        Add-Finding -Severity $p.Severity -Category 'persistence' `\n                    -Label $p.Label -Detail $fullPath\n    } else {\n        Write-OK \"$($p.Label) \u2014 not found\"\n    }\n}\n\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n# 3. PROCESSES\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nWrite-Header \"3/5 \u2014 Running processes\"\n\nforeach ($proc in $SUSPICIOUS_PROCESSES) {\n    $running = Get-Process -ErrorAction SilentlyContinue | Where-Object {\n        $_.ProcessName -match $proc.Pattern -or\n        ($_.MainModule -and $_.MainModule.FileName -match $proc.Pattern)\n    }\n    if ($running) {\n        foreach ($r in $running) {\n            Add-Finding -Severity $proc.Severity -Category 'process' `\n                        -Label $proc.Label `\n                        -Detail \"PID=$($r.Id)  Name=$($r.ProcessName)\"\n        }\n    } else {\n        Write-OK \"$($proc.Label) \u2014 not running\"\n    }\n}\n\n# gh-token-monitor via scheduled task\nWrite-Section \"Scheduled tasks\"\ntry {\n    $tasks = Get-ScheduledTask -ErrorAction SilentlyContinue |\n             Where-Object { $_.TaskName -match 'bun|tanstack|router|gh-token|monitor' }\n    if ($tasks) {\n        foreach ($t in $tasks) {\n            Add-Finding -Severity 'critical' -Category 'persistence' `\n                        -Label \"Suspicious scheduled task: $($t.TaskName)\" `\n                        -Detail $t.TaskPath\n        }\n    } else {\n        Write-OK \"No suspicious scheduled tasks found\"\n    }\n} catch {\n    Write-Host \"  [INFO] Could not query scheduled tasks: $_\" -ForegroundColor DarkGray\n}\n\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n# 4. NETWORK \u2014 Active connections to C2 domains\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nWrite-Header \"4/5 \u2014 Active network connections to C2\"\n\n$tcpConnections = Get-NetTCPConnection -ErrorAction SilentlyContinue\nforeach ($domain in $C2_DOMAINS) {\n    try {\n        $resolved = [System.Net.Dns]::GetHostAddresses($domain) | Select-Object -ExpandProperty IPAddressToString\n    } catch { $resolved = @() }\n\n    $hit = $tcpConnections | Where-Object {\n        $resolved -contains $_.RemoteAddress\n    }\n    if ($hit) {\n        foreach ($c in $hit) {\n            Add-Finding -Severity 'critical' -Category 'network' `\n                        -Label \"Active connection to C2: $domain\" `\n                        -Detail \"Local=$($c.LocalAddress):$($c.LocalPort)  Remote=$($c.RemoteAddress):$($c.RemotePort)  PID=$($c.OwningProcess)\"\n        }\n    } else {\n        Write-OK \"$domain \u2014 no active connection\"\n    }\n}\n\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n# 5. SUSPICIOUS STRINGS in .json / .js / .mjs / .lock / .txt files\n#    (limited to user profile \u2014 not full disk scan)\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nWrite-Header \"5/5 \u2014 Suspicious strings in config / source files\"\n\n$stringScanExtensions = @('*.json', '*.js', '*.mjs', '*.lock', '*.txt', '*.yml', '*.yaml')\n$stringScanRoots = @(\n    $env:USERPROFILE\n    $env:APPDATA\n    $env:LOCALAPPDATA\n) | Where-Object { $_ -and (Test-Path $_) } | Sort-Object -Unique\n\n# Build one combined regex for efficiency\n$combinedPattern = ($SUSPICIOUS_STRINGS | ForEach-Object { [Regex]::Escape($_.Pattern) }) -join '|'\n$combinedRegex   = [System.Text.RegularExpressions.Regex]::new($combinedPattern, [System.Text.RegularExpressions.RegexOptions]::IgnoreCase)\n\n# Track found strings to avoid duplicate reporting per string\n$foundStrings = @{}\n\nforeach ($root in $stringScanRoots) {\n    foreach ($ext in $stringScanExtensions) {\n        try {\n            $files = Get-ChildItem -Path $root -Recurse -Filter $ext `\n                -ErrorAction SilentlyContinue -Force 2&amp;gt;$null |\n                Where-Object { $_.Length -lt 5MB }  # skip huge files\n            foreach ($f in $files) {\n                try {\n                    $content = [System.IO.File]::ReadAllText($f.FullName, [System.Text.Encoding]::UTF8)\n                    $m = $combinedRegex.Match($content)\n                    if ($m.Success) {\n                        $key = \"$($f.FullName)|$($m.Value)\"\n                        if (-not $foundStrings.ContainsKey($key)) {\n                            $foundStrings[$key] = $true\n                            $ioc = $SUSPICIOUS_STRINGS | Where-Object {\n                                $content -imatch [Regex]::Escape($_.Pattern)\n                            } | Select-Object -First 1\n                            Add-Finding -Severity ($ioc ? $ioc.Severity : 'critical') `\n                                        -Category 'string' `\n                                        -Label \"Campaign marker found: `\"$($m.Value)`\"\" `\n                                        -Detail $f.FullName\n                        }\n                    }\n                } catch { &amp;lt;# skip unreadable files #&amp;gt; }\n            }\n        } catch { &amp;lt;# skip inaccessible dirs #&amp;gt; }\n    }\n}\n\n# Check compromised packages in package.json / package-lock.json\nWrite-Section \"Compromised packages in package.json\"\n$pkgFiles = Get-ChildItem -Path $env:USERPROFILE -Recurse -ErrorAction SilentlyContinue `\n    -Include 'package.json','package-lock.json' -Force 2&amp;gt;$null |\n    Where-Object { $_.Length -lt 2MB -and $_.FullName -notmatch '\\\\node_modules\\\\' }\n\n$pkgHits = @{}\nforeach ($f in $pkgFiles) {\n    try {\n        $raw = [System.IO.File]::ReadAllText($f.FullName)\n        foreach ($pkg in $COMPROMISED_PACKAGES) {\n            if ($raw -imatch [Regex]::Escape($pkg)) {\n                $key = \"$($f.FullName)|$pkg\"\n                if (-not $pkgHits.ContainsKey($key)) {\n                    $pkgHits[$key] = $true\n                    Add-Finding -Severity 'critical' -Category 'package' `\n                                -Label \"Compromised package referenced: $pkg\" `\n                                -Detail $f.FullName\n                }\n            }\n        }\n    } catch { &amp;lt;# skip #&amp;gt; }\n}\n\nif ($pkgHits.Count -eq 0) {\n    Write-OK \"No compromised packages found in package.json files\"\n}\n\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n# SUMMARY\n# \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n\nWrite-Header \"SUMMARY \u2014 $hostname \u2014 $auditDate\"\n\n$criticalCount = ($findings | Where-Object { $_.Severity -eq 'critical' }).Count\n$highCount     = ($findings | Where-Object { $_.Severity -eq 'high' }).Count\n$total         = $findings.Count\n\nif ($total -eq 0) {\n    Write-Host \"`n  \u2714  NO ARTEFACTS FOUND \u2014 Likely false positive.\" -ForegroundColor Green\n    Write-Host \"     The previous report matched only command-history traces, not real files.\" -ForegroundColor Gray\n    Write-Host \"     Recommended: keep monitoring, no immediate escalation required.`n\" -ForegroundColor Gray\n} else {\n    Write-Host \"`n  \u2718  $total finding(s): $criticalCount CRITICAL, $highCount HIGH\" -ForegroundColor Red\n    Write-Host \"\"\n\n    if ($criticalCount -gt 0) {\n        Write-Host \"  MANDATORY INCIDENT RESPONSE ORDER:\" -ForegroundColor Red\n        Write-Host \"   1. ISOLATE the machine from the network NOW (do not revoke tokens yet)\" -ForegroundColor Yellow\n        Write-Host \"   2. PRESERVE evidence \u2014 do not reboot, do not delete files\" -ForegroundColor Yellow\n        Write-Host \"   3. IMAGE the disk if possible\" -ForegroundColor Yellow\n        Write-Host \"   4. KILL the gh-token-monitor daemon (if running)\" -ForegroundColor Yellow\n        Write-Host \"   5. THEN revoke and rotate all exposed secrets\" -ForegroundColor Yellow\n        Write-Host \"   6. ESCALATE to CSIRT with this output and the CSV report\" -ForegroundColor Yellow\n    }\n\n    Write-Host \"`n  Findings detail:\" -ForegroundColor DarkYellow\n    foreach ($f in $findings) {\n        $color = if ($f.Severity -eq 'critical') { 'Red' } elseif ($f.Severity -eq 'high') { 'Yellow' } else { 'Magenta' }\n        Write-Host \"    [$($f.Severity.ToUpper())][$($f.Category)] $($f.Label)\" -ForegroundColor $color\n        if ($f.Detail) {\n            Write-Host \"       $($f.Detail)\" -ForegroundColor DarkGray\n        }\n    }\n    Write-Host \"\"\n}\n", "creation_timestamp": "2026-05-19T12:35:06.000000Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/d1468a0b-3c9f-4c39-a594-51b349525778/export"/>
    <published>2026-05-19T12:35:06+00:00</published>
  </entry>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/2648544c-b880-417c-af79-7055a59d8e9a/export</id>
    <title>2648544c-b880-417c-af79-7055a59d8e9a</title>
    <updated>2026-06-06T07:29:31.430204+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://cve.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "2648544c-b880-417c-af79-7055a59d8e9a", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-45321", "type": "seen", "source": "Telegram/Nb7K5zYmouklHSq2-4YzAjIlBSlI43wf9hUI3PLTIzXqPwQ", "content": "", "creation_timestamp": "2026-05-21T03:00:06.000000Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/2648544c-b880-417c-af79-7055a59d8e9a/export"/>
    <published>2026-05-21T03:00:06+00:00</published>
  </entry>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/a5e02480-6260-488e-96d9-101218a87481/export</id>
    <title>a5e02480-6260-488e-96d9-101218a87481</title>
    <updated>2026-06-06T07:29:31.430067+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://cve.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "a5e02480-6260-488e-96d9-101218a87481", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-45321", "type": "seen", "source": "https://t.me/GithubRedTeam/85990", "content": "\ud83d\udea8 GitHub \u76d1\u63a7\u6d88\u606f\u63d0\u9192\n\n\ud83d\udea8 \u53d1\u73b0\u5173\u952e\u8bcd\uff1a #CVE-2026 #Exploit\n\n\ud83d\udce6 \u9879\u76ee\u540d\u79f0\uff1a tanscript-exploit-check\n\ud83d\udc64 \u9879\u76ee\u4f5c\u8005\uff1a nkopylov\n\ud83d\udee0 \u5f00\u53d1\u8bed\u8a00\uff1a Shell\n\u2b50 Star\u6570\u91cf\uff1a 1  |  \ud83c\udf74 Fork\u6570\u91cf\uff1a 0\n\ud83d\udcc5 \u66f4\u65b0\u65f6\u95f4\uff1a 2026-05-26 14:46:38\n\n\ud83d\udcdd \u9879\u76ee\u63cf\u8ff0\uff1a\nIOC checker for the TanStack/Mini Shai-Hulud npm supply chain attack (CVE-2026-45321)\n\n\ud83d\udd17 \u70b9\u51fb\u8bbf\u95ee\u9879\u76ee\u5730\u5740", "creation_timestamp": "2026-05-26T15:00:08.000000Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/a5e02480-6260-488e-96d9-101218a87481/export"/>
    <published>2026-05-26T15:00:08+00:00</published>
  </entry>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/e09aa07b-11ba-4231-88f3-8d6fc11563f7/export</id>
    <title>e09aa07b-11ba-4231-88f3-8d6fc11563f7</title>
    <updated>2026-06-06T07:29:31.429912+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://cve.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "e09aa07b-11ba-4231-88f3-8d6fc11563f7", "vulnerability_lookup_origin": "405284c2-e461-4670-8979-7fd2c9755a60", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-45321", "type": "exploited", "source": "https://vulnerability.circl.lu/known-exploited-vulnerabilities-catalog/5eca6dd4-073c-4bd1-b174-250eb902c1bf", "content": "", "creation_timestamp": "2026-05-27T18:00:02.338954Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/e09aa07b-11ba-4231-88f3-8d6fc11563f7/export"/>
    <published>2026-05-27T18:00:02.338954+00:00</published>
  </entry>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/a2c4a233-7346-4610-ab31-03a41d4cf000/export</id>
    <title>a2c4a233-7346-4610-ab31-03a41d4cf000</title>
    <updated>2026-06-06T07:29:31.429776+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://cve.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "a2c4a233-7346-4610-ab31-03a41d4cf000", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-45321", "type": "seen", "source": "https://bsky.app/profile/cvesentinel.bsky.social/post/3mmu45ujto42h", "content": "\ud83d\uded1 CVE-2026-45321\nTanStack TanStack\nCVSS 9.6 / EPSS 0% / KEV\nTL;DR: On 2026-05-11, between approximately 19:20 and 19:26 UTC, 84 malicious versions across 42 @ta\u2026\nhttps://cvesentinel.com/report/CVE-2026-45321?utm_source=bluesky&amp;amp;utm_medium=social&amp;amp;utm_campaign=cvesentinel\n#infosec #CVE #vulnerability", "creation_timestamp": "2026-05-27T18:10:43.905534Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/a2c4a233-7346-4610-ab31-03a41d4cf000/export"/>
    <published>2026-05-27T18:10:43.905534+00:00</published>
  </entry>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/80d9955a-5970-46de-81f4-fbe887842a54/export</id>
    <title>80d9955a-5970-46de-81f4-fbe887842a54</title>
    <updated>2026-06-06T07:29:31.429646+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://cve.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "80d9955a-5970-46de-81f4-fbe887842a54", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-45321", "type": "seen", "source": "https://feedsin.space/feed/CISAKevBot/items/6591184", "content": "2026-05-27: [CVE-2026-45321] TanStack Unspecified VulnerabilityTanStack contains an unspecified vulnerability that allowed malicious versions of the product to be published to the npm registry to publish credential-stealing malware under a trusted identity.\ncisakev", "creation_timestamp": "2026-05-27T19:09:44.103279Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/80d9955a-5970-46de-81f4-fbe887842a54/export"/>
    <published>2026-05-27T19:09:44.103279+00:00</published>
  </entry>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/b12e9c3d-2d1a-4f53-a2b2-24f38c9221db/export</id>
    <title>b12e9c3d-2d1a-4f53-a2b2-24f38c9221db</title>
    <updated>2026-06-06T07:29:31.429477+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://cve.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "b12e9c3d-2d1a-4f53-a2b2-24f38c9221db", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-45321", "type": "seen", "source": "https://bsky.app/profile/boredchilada.bsky.social/post/3mmucnfq3w323", "content": "~Cisa~\nCISA added three actively exploited vulnerabilities to the KEV catalog.\n-\nIOCs: CVE-2026-8398, CVE-2026-45321, CVE-2026-48027\n-\n#CISA #KEV #threatintel", "creation_timestamp": "2026-05-27T20:06:47.560330Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/b12e9c3d-2d1a-4f53-a2b2-24f38c9221db/export"/>
    <published>2026-05-27T20:06:47.560330+00:00</published>
  </entry>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/80a62ae9-173e-445f-bbff-47e0aa92b200/export</id>
    <title>80a62ae9-173e-445f-bbff-47e0aa92b200</title>
    <updated>2026-06-06T07:29:31.427625+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://cve.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "80a62ae9-173e-445f-bbff-47e0aa92b200", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2026-45321", "type": "seen", "source": "https://bsky.app/profile/cyberlensai.bsky.social/post/3mneb24qjwh2p", "content": "CVE watch: CVE-2026-45321: TanStack TanStack \u2014 TanStack Unspecified\u2026\n\nCheck exposure, dependency, and agent/tool access before panic-patching. Inventory beats vibes.\n\nSource: cisa.gov\nhttps://www.cisa.gov/known-exploited-vulnerabilities-catalog?search_api_fulltext=CVE-2026-45321", "creation_timestamp": "2026-06-03T04:20:42.476990Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/80a62ae9-173e-445f-bbff-47e0aa92b200/export"/>
    <published>2026-06-03T04:20:42.476990+00:00</published>
  </entry>
</feed>
