Socket’s Threat Research Team discovered a Shai-Hulud-like supply chain worm campaign tracked as SANDWORM_MODE that spread through at least 19 typosquatting npm packages and a malicious GitHub Action, harvesting developer and CI secrets, exfiltrating via HTTPS/GitHub API/DNS, and persisting via git hooks and MCP server injection targeting AI coding assistants. npm, GitHub, and Cloudflare removed related infrastructure, but defenders must treat the identified packages and injected workflows as active compromise risks and rotate/revoke affected tokens, audit global git templates, and inspect AI assistant configs for rogue MCP servers. #SANDWORM_MODE #suport-color
Keypoints
- At least 19 typosquatting npm packages (published under two publisher aliases) delivered a multi-stage Shai-Hulud-like worm tracked as SANDWORM_MODE that runs on import while preserving expected library behavior.
- The payload immediately steals high-value crypto keys and then, after a 48–96 hour time gate (bypassed in CI), decrypts a Stage 2 bundle that performs deep harvesting, propagation, MCP server injection, git-hook persistence, and multi-channel exfiltration.
- Exfiltration uses a three-channel cascade: HTTPS POST to a Cloudflare Worker, authenticated GitHub API uploads to attacker repos, and DNS tunneling with a DGA fallback seeded by “sw2025”.
- Propagation is automated via three vectors: abusing stolen npm tokens to publish carrier packages, using stolen GitHub tokens to inject dependencies and workflows (pull_request_target), and an SSH-based fallback that clones and pushes with victim identities.
- The campaign includes targeted tampering of AI toolchains: it deploys a rogue MCP server with embedded prompt injection into local AI assistant configs and harvests API keys for nine LLM providers.
- Detection-evasion and persistence techniques include obfuscated runtime loaders (base64 + zlib + XOR + eval or in-memory Module._compile), polymorphic engine scaffolding (disabled in this build), and global git init.templateDir hook persistence; the dead-switch destructive routine is present but disabled.
MITRE Techniques
- [T1195 ] Software Supply Chain Compromise – Typosquatting and look-alike packages used as initial foothold (‘typosquatting npm packages’ / ‘suport-color impersonates supports-color’)
- [T1078 ] Valid Accounts – Abusing stolen npm and GitHub tokens to authenticate, publish packages, and modify repositories (‘abusing stolen npm and GitHub identities to move laterally through the software supply chain’)
- [T1552.001 ] Credentials in Files – Harvesting tokens and credentials from configuration and env files (‘.npmrc files (home, cwd, platform-specific paths) → auth tokens’ and ‘.env files in the project root’)
- [T1555 ] Credentials from Password Stores – Extracting secrets from password managers by invoking CLIs (‘Bitwarden, 1Password, LastPass via their respective CLIs’)
- [T1005 ] Data from Local System – Full filesystem and SQLite store scanning for wallet files, notes, and other sensitive local artifacts (‘full filesystem scan for wallet files and crypto configs beyond the working directory’)
- [T1041 ] Exfiltration Over C2 Channel – Multi-channel exfiltration including HTTPS to a Cloudflare Worker and authenticated GitHub uploads (‘HTTPS POST to a Cloudflare Worker’ and ‘authenticated GitHub API uploads to threat actor-created private repositories’)
- [T1071.001 ] Application Layer Protocol: Web Protocols – Use of HTTPS and GitHub API for data exfiltration and C2 (‘exfiltrates them via HTTPS with DNS fallback’ / ‘exfiltrates data via the GitHub API’)
- [T1048 ] Exfiltration Over Alternative Protocol (DNS) – DNS tunneling and base32-encoded DNS queries used as a fallback and interleaved cover traffic (‘DNS tunneling via base32-encoded queries to freefan[.]net (primary) and fanfree[.]net (secondary)’)
- [T1027 ] Obfuscated Files or Information – Runtime obfuscation and staged loaders to hide payloads (‘a large embedded base64 blob is decompressed with zlib.inflateSync() and executed via eval()’ and ‘XOR-decrypted with a static 32-byte key’)
- [T1547 ] Boot or Logon Autostart Execution (configuration persistence) – Persisting via git template configuration so new repositories inherit malicious hooks (‘git config –global init.templateDir so new repositories inherit malicious hooks’)
- [T1059 ] Command and Scripting Interpreter – Dynamic script execution using eval() and in-memory Module._compile() to run malicious JavaScript at import time (‘executed entirely in memory via Node’s internal Module._compile() API’ and ‘(0,eval)(d);’)
Indicators of Compromise
- [npm packages ] Malicious typosquat packages delivering SANDWORM_MODE – [email protected], [email protected], and other 17 packages (full list includes [email protected], [email protected], etc.).
- [Domains ] Exfiltration and DNS C2 domains – freefan[.]net, fanfree[.]net, and DGA domains across TLDs (cc, io, xyz, top, pw, tk, ws, gg, ly, mx).
- [C2 endpoints (HTTPS) ] Cloudflare Worker exfil endpoints – https://pkg-metrics[.]official334[.]workers[.]dev/exfil, https://pkg-metrics[.]official334[.]workers[.]dev/drain.
- [GitHub repository / Action ] Malicious CI Action and repo – ci-quality/code-quality-check (user: official334) with entrypoint dist/index.js and propagate core in dist/propagate-core.js.
- [npm publisher aliases ] Attacker publisher identities – official334, javaorg.
- [Email addresses ] Operator contact addresses observed – official334@proton[.]me, JAVAorg@proton[.]me.
- [Bearer token ] Drain authentication token used for initial exfiltration – fa31c223d78b02d2315770446b9cb6f79ffc497db36d0f0b403e77ff4466cafb.
- [Cryptographic artifacts ] Stage 2 AES and integrity parameters – IV (base64): dko6mG8AmQVECvVP, Auth Tag (base64): /6rzsm9K+mflC4uguMJriA==, Stage 2 AES key (hex): 5ce544f624fd2aee173f4199da62818ff78deca4ba70d9cf33460974d460395c.
- [Injected workflow filename ] CI workflow and injection artifacts – .github/workflows/quality.yml and injected pull_request_target workflows that serialize ${{ toJSON(secrets) }} for exfiltration.
- [Local LLM / MCP endpoints ] Local probing and MCP server artifacts – local LLM endpoints such as http://localhost:11434/api/generate and deployed rogue server path example ~/.dev-utils/server.js (MCP server entries written into Claude/Cursor/VS Code configs).
Read more: https://socket.dev/blog/sandworm-mode-npm-worm-ai-toolchain-poisoning