Mini Shai-Hulud Strikes Again: 314 npm Packages Compromised - Real-time Open Source Software Supply Chain Security<br>Login Book a Demo 1.3k
Back<br>Vet<br>Scan and govern your dependencies across every PR and build.
PMG<br>Block malicious packages at install-time, before they enter your codebase.
xbom<br>Generate AI-enriched BOMs using real code evidence, not just manifests.
GRYPH<br>Monitor every AI coding agent action across your projects and workflows.
BackDiscover & Monitor<br>SCA & SBOMScan dependencies, generate SBOMs, enforce policy.
AI Agent DiscoverySee every AI tool and SDK in your org.
AI Agent MonitoringAudit every action your AI agents take.
Protect<br>Developer SecurityBlock malicious packages at install-time.
CI/CD SecurityBlock malicious packages in your pipeline.
MCP ServerBlock threats inside your AI coding agent.
Agent APIThreat intelligence API for custom agents.
Threat IntelligenceReal-time malicious package verdicts.
Govern<br>PlatformCentralized policies, dashboard, compliance.
Login Book a Demo 1.3k
Back to Blog
Mini Shai-Hulud Strikes Again: 314 npm Packages Compromised<br>Malware
SafeDep Team<br>• May 19, 2026 • 18 min read
Table of Contents
TL;DR<br>The npm account atool ([email protected]) was compromised on May 19, 2026. The attacker published 631 malicious versions across 314 packages in a 22-minute automated burst. Affected packages include size-sensor (4.2M downloads/month), echarts-for-react (3.8M), @antv/scale (2.2M), timeago.js (1.15M), and hundreds of @antv scoped packages. The payload is a 498KB obfuscated Bun script that matches the Mini Shai-Hulud toolkit used in the SAP compromise three weeks earlier: same scanner architecture, same credential regex set, same obfuscation pattern. It harvests credentials across the full AWS chain (env vars, config files, EC2 IMDS, ECS container metadata, Secrets Manager), Kubernetes service account tokens, HashiCorp Vault, GitHub PATs, npm tokens, SSH keys, and more. Stolen data is exfiltrated by committing it as Git objects to public GitHub repositories created under the compromised token, with the User-Agent forged as python-requests/2.31.0. In CI environments, the payload exchanges GitHub Actions OIDC tokens for npm publish tokens, signs artifacts via Sigstore (Fulcio + Rekor) using the stolen identity, and injects persistence into .github/workflows/codeql.yml. The payload also targets Claude Code configuration files (.claude/settings.json, .claude/setup.mjs) for AI agent compromise, attempts Docker container escape via the host socket, and propagates infection to other local Node.js projects.<br>The attack uses two execution paths. Each compromised version adds a preinstall hook (bun run index.js). 630 of 631 versions also inject an optionalDependencies entry pointing to imposter commits in the antvis/G2 GitHub repository. These are orphan commits with forged authorship, invisible in the repo’s branch history, exploiting GitHub’s fork object sharing to host a second copy of the payload without any write access to the target repository. npm’s github: dependency resolution fetches and executes the content by SHA.<br>Impact:<br>Projects using semver ranges (e.g., ^3.0.6 for echarts-for-react) auto-resolve to compromised versions<br>Credential harvesting targets npm tokens, GitHub PATs, AWS keys (full credential chain including EC2 metadata and ECS container credentials), GCP service accounts, Azure credentials, database connection strings, Stripe keys, Slack tokens, SSH keys, Docker auth, Kubernetes service account tokens, and HashiCorp Vault tokens<br>Exfiltrated data is committed to public GitHub repositories created under the stolen token’s account, using the GitHub API as a C2 channel disguised with a python-requests/2.31.0 User-Agent<br>npm OIDC token exchange in CI allows the attacker to obtain publish tokens using the pipeline’s own identity<br>Sigstore signing with stolen OIDC tokens creates legitimately-signed artifacts with forged provenance<br>Docker socket access enables privileged container escape with host filesystem bind mounts<br>CI/CD persistence via .github/workflows/codeql.yml injection on a chore/add-codeql-static-analysis branch<br>Claude Code configuration targeting (.claude/settings.json, .claude/setup.mjs) for AI agent compromise<br>Local project infection propagates preinstall hooks to other Node.js projects on the same machine<br>Redundant payload delivery via GitHub imposter commits survives even if preinstall hooks are blocked<br>Indicators of Compromise (IoC):<br>Any package published by atool ([email protected]) on 2026-05-19 between 01:44 and 02:06 UTC<br>preinstall script: bun run index.js<br>Payload SHA256: a68dd1e6a6e35ec3771e1f94fe796f55dfe65a2b94560516ff4ac189390dfa1c<br>Imposter commits in antvis/G2 (orphan, forged author, message: “New Package”):1916faa365f2788b6e193514872d51a242876569 (626 versions)<br>7cb42f57561c321ecb09b4552802ae0ac55b3a7a (2 versions)<br>dc3d62a2181beb9f326952a2d212900c94f2e13d (1 version, garbage collected)
Optional dependency: @antv/setup:...