
StepSecurity + Endor Labs: Mini-Shai-Hulud Wave 2
StepSecurity and Endor Labs document a second wave of the Mini Shai-Hulud npm worm spreading through the compromised 'atool' account, which publishes timeago.js and maintains packages in Alibaba's @antv namespace, hitting echarts-for-react, jest-canvas-mock and dozens of other packages. The payload scrapes GitHub Actions Runner.Worker process memory to steal masked CI/CD secrets, harvests 130+ credential file paths (cloud, SSH, Kubernetes, Vault, crypto wallets, Claude Code/VS Code configs), exfiltrates via a GitHub API dead-drop in antvis/G2 or a fake-OpenTelemetry C2 at t.m-kosche.com, drops persistent backdoors in Claude Code/VS Code, and has already used stolen GitHub tokens to spin up 2,500+ dead-drop repositories. The writeup includes full process/network telemetry from Harden-Runner showing the attack blocked, deobfuscated payload internals, IOCs, and detection/remediation guidance.
What it is
A StepSecurity + Endor Labs runtime analysis of the "Mini Shai-Hulud Wave 2" npm worm, observed by installing echarts-for-react@3.0.7 inside a GitHub Actions workflow protected by Harden-Runner. The compromised atool npm account publishes timeago.js (1.5M weekly downloads) and @antv packages; the affected list is still growing while the attack is ongoing.
How it works
The malicious version ships as an optionalDependencies git reference. npm install clones a poisoned antvis/G2 commit (codeload.github.com/antvis/G2/tar.gz/7cb42f57...), which runs a prepare hook that downloads the Bun runtime and executes index.js. The payload then:
- runs
ghfor GitHub CLI reconnaissance; - uses
sudoto spawnpython3reading/proc/2175/mem— theRunner.Workerprocess — and pipes it throughtr | grep isSecret:true | sortto pull masked CI/CD secrets out in plaintext; - harvests credentials from 130+ file paths (AWS, GCP, Azure, Kubernetes, Vault, crypto wallets);
- exfiltrates via a GitHub API dead-drop in
antvis/G2and a fallback C2 att.m-kosche.com, POSTing to a fake OpenTelemetry endpointapi/public/otel/v1/traces.
Detail not in the summary: the payload also drops persistent backdoors into Claude Code and VS Code configurations that survive across sessions. For echarts-for-react@3.0.7 the clone/scrape pattern repeated four times (four python3 PIDs all reading /proc/2175/mem).
flowchart TD
A[npm install echarts-for-react@3.0.7] --> B[node: resolve github:antvis/G2, install bun]
B --> C[dash: prepare hook]
C --> D[bun.exe: index.js payload]
D --> E[gh: recon]
D --> F[sudo python3: read /proc/PID/mem Runner.Worker]
F --> G[tr | grep isSecret:true | sort]
D --> H[Backdoor Claude Code + VS Code]
G --> I{Exfil}
I --> J[GitHub dead-drop antvis/G2]
I --> K[C2 t.m-kosche.com fake OTel]Preconditions / Affected
CI/CD environments (GitHub Actions) that install any compromised atool/@antv package. Masked secrets are exposed because they live in Runner.Worker memory the payload can read.
What to do
- If you installed any affected package, assume all secrets in that environment are compromised and rotate all credentials immediately.
- Check Claude Code and VS Code configs for persistent backdoors — these survive session restarts.
- Two Harden-Runner default protections each independently stopped the attack: the Global Block List blocked
t.m-kosche.com, and memory-access detection on/proc/PID/memtriggered a lockdown that terminated the run. Either alone was sufficient. - Hunt indicators: outbound
t.m-kosche.com, GitHub repos named with Dune terminology and the reversed descriptionniagA oG eW ereH :duluH-iahS.
Caveats
The full telemetry was only captured by deliberately disabling the Block List and lockdown mode in a second run; with defaults on, the attack was blocked before completion. The compromised-package list was incomplete and growing at publication.
Organisations named here
- antvis/G2
- t.m-kosche.com
Technologies named here
- Harden-Runner
- echarts-for-react
- StepSecurity Secure Registry
- timeago.js
- @antv/graphlib
- StepSecurity Dev Machine Guard
- @antv/* namespace packages
- npm Package Cooldown Check
- NPM Package Compromised Updates Check
- jest-canvas-mock
- jest-date-mock
- npm Package Search
- size-sensor
- AI Package Analyst
- lint-md
- StepSecurity Threat Center
- antvis/G2 GitHub repository
- npm
- GitHub Actions
- Bun
- VS Code
- Claude Code
- StepSecurity
- AntV
Techniques named here
- Runner.Worker Memory Scraping
- CI/CD environment variable theft
- Credential file harvesting
- Dual-channel exfiltration
- Direct install hook
- optionalDependencies git reference
- Double-publish version bump
- Daemonization / background execution
- Persistence via IDE/tool config backdoors
- Privilege escalation via sudoers rule
- Payload obfuscation
- GitHub token reuse for infrastructure creation
Threat actors named here
- Mini Shai-Hulud
- atool
Related in Supply Chain


