A worm that now infects your editor, not just your dependencies

JFrog’s security research team confirmed a fresh Shai-Hulud wave in August 2026, starting with the keyv and cacheable npm packages and spreading to 400+ packages across 1,700+ versions. The core mechanics are familiar: a preinstall hook runs node setup.mjs, which fetches a Bun runtime and executes the real payload, math_init.js, which harvests npm tokens, cloud credentials, SSH keys, Kubernetes secrets, and browser-stored secrets. Tokens with bypass_2fa === true and publish rights let the worm republish infected versions of every package the stolen token can touch — classic self-propagation.

What’s new — and what most existing supply-chain detection content doesn’t cover — is the persistence step. Once the payload has repo access, it commits files that auto-execute the moment a developer opens the repository in tooling they trust: .vscode/tasks.json (VS Code can auto-run tasks on folder open) and .claude/settings.json (used to alter Claude Code’s permission/hook behavior). It also drops GitHub Actions workflow changes that exfiltrate secrets via artifact downloads, and on Linux CI runners it reads /proc/<pid>/mem to lift secrets directly out of process memory. This turns a developer’s own editor and AI coding assistant into the trigger for reinfection, even after the malicious npm package itself is removed.

Detection priorities

  1. Repos gaining new or modified .vscode/tasks.json with runOn: folderOpen
  2. New or modified .claude/settings.json / .claude/settings.local.json outside normal developer workflow
  3. node processes spawning a Bun download/install, then executing scripts named setup.mjs or math_init.js
  4. Anomalous /proc/<pid>/mem reads by Node processes on Linux
  5. Git commits containing the campaign’s known markers

Sigma — auto-run VS Code task committed to a repository

This rule is best run against a git-hook/CI scanning pipeline or an EDR file-content inspection capability rather than raw file creation, since tasks.json is a legitimate file — the signal is the auto-run trigger plus a suspicious command.

title: Suspicious Auto-Executing VS Code Task Added to Repository
id: 8b1a6f4e-2c9d-4e7b-9a3f-6d5c1e8b7a02
status: experimental
description: >
  Detects .vscode/tasks.json files configured to run automatically on folder
  open (runOn: folderOpen) that invoke node, bash, curl, or npm — the
  persistence pattern used by the August 2026 Shai-Hulud npm worm wave to
  reinfect developer machines when a repo is opened in VS Code.
references:
  - https://research.jfrog.com/post/shai-hulud-is-back-august/
logsource:
  category: file_event
  product: linux
detection:
  selection_file:
    TargetFilename|endswith: '/.vscode/tasks.json'
  selection_content:
    FileContent|contains:
      - 'runOn'
      - 'folderOpen'
  suspicious_command:
    FileContent|contains:
      - 'setup.mjs'
      - 'math_init.js'
      - 'curl'
      - 'bun install'
  condition: selection_file and selection_content and suspicious_command
falsepositives:
  - Legitimate build tasks configured to run on folder open (rare in practice)
level: high
tags:
  - attack.persistence
  - attack.t1546

Sigma — Claude Code settings modified with new hooks/permissions

title: Claude Code Settings Modified With New Hooks or Auto-Approve Permissions
id: 3f7e2c91-5b8a-4d6f-91c2-7a4e0b8d3f56
status: experimental
description: >
  Detects creation or modification of .claude/settings.json or
  .claude/settings.local.json containing new "hooks" entries or permission
  bypass fields, consistent with supply-chain persistence that abuses
  AI coding assistants to auto-execute payloads on repo open.
references:
  - https://research.jfrog.com/post/shai-hulud-is-back-august/
logsource:
  category: file_event
  product: linux
detection:
  selection_path:
    TargetFilename|contains:
      - '/.claude/settings.json'
      - '/.claude/settings.local.json'
  selection_content:
    FileContent|contains:
      - '"hooks"'
      - 'bypassPermissions'
      - 'dangerouslySkipPermissions'
  filter_known_admin:
    Image|endswith:
      - '\code.exe'
      - '/bin/code'
  condition: selection_path and selection_content and not filter_known_admin
falsepositives:
  - Developers intentionally configuring hooks for local automation
level: medium
tags:
  - attack.persistence
  - attack.t1554

Sigma — npm worm install-time execution chain

title: Node Preinstall Script Downloading Bun and Executing Payload
id: 9a2d5e8c-1f4b-4a7d-b3e9-0c6f8a2d5e17
status: experimental
description: Detects the setup.mjs/math_init.js execution chain used by Shai-Hulud npm worm variants during package install.
logsource:
  category: process_creation
  product: linux
detection:
  parent_selection:
    ParentImage|endswith: '/npm'
    ParentCommandLine|contains: 'install'
  selection:
    Image|endswith: '/node'
    CommandLine|contains:
      - 'setup.mjs'
      - 'math_init.js'
  condition: parent_selection and selection
level: critical
tags:
  - attack.execution
  - attack.t1195.002

KQL — hunting for the campaign’s commit markers and secret-exfil workflows

// GitHub audit log: commits or workflow changes matching known Shai-Hulud markers
GitHubAuditLogs
| where Category in ("git", "workflows")
| where AdditionalFields has_any ("thebeautifulmarchoftime", "thebeautifulsnadsoftime")
   or ActionType == "workflows.create_or_update"
      and AdditionalFields has "upload-artifact"
| project TimeGenerated, ActorLogin, Repository, ActionType, AdditionalFields
| order by TimeGenerated desc
// Detect Node processes reading /proc/<pid>/mem on Linux CI runners (memory-scraping for secrets)
DeviceProcessEvents
| where FileName == "node" or FileName == "bun"
| where ProcessCommandLine has "/proc/" and ProcessCommandLine has "/mem"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName

Response notes

If any of these fire, treat the finding as active credential compromise, not just malware presence: rotate every npm token, GitHub PAT, cloud key, and SSH key reachable from the affected workstation or CI runner, and audit recently published package versions under any implicated npm account for unauthorized patch bumps. Strip .vscode/tasks.json and .claude/settings*.json changes from the offending branch history rather than just deleting the files, since the trigger persists in git history until force-pushed out or the branch is rebuilt.

Sources: JFrog Security Research — Shai-Hulud is back, August, JFrog — Shai-Hulud npm supply chain attack, new compromised packages detected