Skip to content

Add New ChainDrop NPM Supply-Chain Attack Rules - #6219

Open
harshthakur6293 wants to merge 1 commit into
SigmaHQ:masterfrom
harshthakur6293:dev/emerging-threats-chaindrop-npm-worm
Open

Add New ChainDrop NPM Supply-Chain Attack Rules#6219
harshthakur6293 wants to merge 1 commit into
SigmaHQ:masterfrom
harshthakur6293:dev/emerging-threats-chaindrop-npm-worm

Conversation

@harshthakur6293

@harshthakur6293 harshthakur6293 commented Aug 11, 2026

Copy link
Copy Markdown

Adds 7 rules for the ChainDrop npm supply-chain worm (Mini Shai-Hulud variant) reported on 2026-08-04, which compromised the keyv and cacheable package families and spread to 444 packages across 2,212 versions.

Placed in rules-emerging-threats/2026/Malware/ChainDrop/, following the layout of the TanStack pack from #6008. Purely additive, no existing files changed.

Why existing rules do not cover this

The repo already has Shai-Hulud (2025) and TanStack (2026) packs. I checked each against the ChainDrop artefacts and none of them fire, because every selector keys on something this wave replaced:

  • ..._shai_hulud_malicious_node_bun_execution keys on bun_environment.js and bun.sh/install. ChainDrop uses Math_Symbol.js / math_init.js and pulls Bun v1.3.13 from the GitHub releases URL.
  • ..._shai_hulud_indicator keys on Shai-Hulud / SHA1HULUD in the command line. In this wave those strings only appear in attacker repo descriptions, never on a command line.
  • ..._shai_hulud_malicious_npm_package_installation keys on a hard-coded Nov-2025 package list. ChainDrop hit keyv@6.0.0, flat-cache@6.1.24, file-entry-cache@11.1.6 and others.
  • ..._shai_hululd_exfiltration keys on the old webhook.site URL. ChainDrop posts to npm-cache.com:443/router.
  • file_event_lnx_mal_shai_hulud_workflow keys on .github/workflows/shai-hulud-workflow.yml. ChainDrop persists via .claude/ and .vscode/ instead.
  • ..._tanstack_supply_chain keys on tanstack_runner.js and .claude/router_runtime.js.
  • dns_query_win_malware_tanstack_supply_chain_c2 keys on git-tanstack.com.

Worth flagging: node setup.mjs is the lead hunting query in both the Microsoft and Elastic write-ups, and it is not in any detection block in this repo today. It appears in the TanStack rule description text only.

Rules

File Covers
proc_creation_{lnx,win}_malware_chaindrop_execution.yml preinstall dropper, Bun download and staging, payload execution
proc_creation_{lnx,win}_malware_chaindrop_credential_access.yml cloud and GitHub token harvesting, Actions runner memory scrape
file_event_{lnx,win}_malware_chaindrop.yml payload drop, .claude / .vscode persistence, gh-token-monitor
dns_query_win_malware_chaindrop_c2.yml exfil and EtherHiding fallback domains

Linux and Windows counterparts are cross-linked with related:.

Detection chain

On an infected host the chain is: npm install runs the preinstall hook, which runs node setup.mjs, which downloads Bun into a bun-dl- temp dir and executes Math_Symbol.js under it. That payload then shells out to gh auth token, az account get-access-token and similar, writes .claude/setup.mjs for persistence, and exfils to npm-cache.com.

The execution rule covers the first three steps, the credential access rule the fourth, the file event rule the fifth, and the DNS rule the last. A hit on the dropper alone tells you a lifecycle hook ran an unexpected script. A hit on the payload or credential selections alongside it means the second stage detonated and tokens need rotating.

False positive handling

The Bun download and credential access selections are gated on ParentImage. This matters because the download URL is the official Bun release URL and gh auth token is an ordinary command. The signal is the parent, not the command:

Command line Parent Result
curl -fsSL .../bun-v1.3.13/bun-linux-x64-baseline.zip node fires
same bash silent
curl -fsSL https://bun.sh/install | bash bash silent
gh auth token bun fires
same bash silent
az account get-access-token bun fires
same sh silent

Credential access is gated on behaviour rather than filename on purpose. This campaign has already renamed its payload twice (bun_environment.js, then tanstack_runner.js, now Math_Symbol.js), which is why the older packs miss it, so a rule keyed on the Bun parent should survive the next rename.

Three published IOCs are deliberately left out because in these log sources they would be false positive generators, not detections:

  • .github/workflows/codeql_analysis.yml is a normal filename. The malicious part is the injected ${{ toJSON(secrets) }} content, which file_event cannot see.
  • .claude/settings.json and .vscode/tasks.json are written constantly by Claude Code and VS Code. Again the malice is in the contents.
  • The Ethereum RPC endpoints used for EtherHiding (eth.llamarpc.com, go.getblock.io, eth-mainnet.nodereal.io) are legitimate infrastructure. Only confirmed attacker apexes are in the DNS rule.

SHA256 hashes from the reports are in references rather than as selectors, since there is no usable hash field here and they do not survive a payload rebuild.

Testing

yamllint --strict                                          pass
python tests/test_logsource.py                             OK (3 tests)
python tests/test_rules.py                                 OK (11 tests)
sigma check --fail-on-error --fail-on-issues \
  --validation-config tests/sigma_cli_conf.yml             0 errors, 0 issues

An earlier revision raised two SigmahqTagsTechniquesWithoutTacticsIssue findings on the file_event rules, since T1546 and T1543.002 map to both Persistence and Privilege Escalation. Fixed by adding attack.privilege-escalation.

I also ran the selectors against a synthetic event set built from the published telemetry: 32 events covering every documented artefact across the five reports were each matched by at least one rule, and 20 benign developer and CI events produced no hits, including the paired cases in the table above plus bun run from node_modules, legitimate .vscode/tasks.json and .claude/settings.json writes, a CodeQL workflow file, an ordinary mathjs/lib/math.js, and registry.npmjs.org DNS.

References

Happy to split this up, adjust tags, or tighten the setup.mjs selector if you prefer. The attack.t1003 tag on the Linux credential access rule covers the /proc/<pid>/mem scrape and can be dropped if t1552.001 is enough.

Adds 7 emerging-threat rules covering the ChainDrop worm (Mini Shai-Hulud
variant) reported 2026-08-04, which compromised the keyv/cacheable package
families and self-propagated to 444 packages across 2,212 versions.

Existing Shai-Hulud (2025) and TanStack (2026) packs do not fire on this
wave: they key on bun_environment.js, tanstack_runner.js, the literal
strings Shai-Hulud/SHA1HULUD, and a hard-coded Nov-2025 package list, all
of which ChainDrop replaced. "node setup.mjs", the lead hunting query in
both the Microsoft and Elastic reports, was not present in any detection
logic in the repository.

Coverage:
  - proc_creation (lnx/win): dropper, Bun ingress, payload execution
  - proc_creation (lnx/win): cloud token harvesting and runner memory scrape
  - file_event (lnx/win): payload drop and .claude/.vscode persistence
  - dns_query: exfiltration and EtherHiding fallback infrastructure

Bun-download and credential-access selections are gated on ParentImage so
that legitimate Bun installs and interactive cloud CLI use stay silent.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Welcome @harshthakur6293 👋

It looks like this is your first pull request on the Sigma rules repository!

Please read the SigmaHQ conventions to ensure your contribution adheres to best practices and includes all the necessary elements for a successful review.

Also check CONTRIBUTING.md for more information on how to contribute to the Sigma rules repository, specifically proper testing and validation of your rules.

Thanks again, and welcome to the Sigma community! 😃

If you want to engage more with the community for official support, general discussions or announcements:

👉 Join our Discord server

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant