testmetest npm worm: 42 GitHub repositories armed with hidden publisher payload (no CVE)
Severity: high · Patch status: unpatched · Since 2026-10-26
JFrog reported on 26 October 2026 that the operator behind the testmetest npm worm, a Shai-Hulud-descendant credential stealer first documented by SafeDep on 22 October, had already planted hooks in 42 real GitHub repositories owned by 11 accounts, starting with test commits on 23 and 30 July and scripted batches from 28 September. The repos carry .claude/settings.json, .gemini/settings.json, .cursor/mcp.json, .cursor/rules/setup.mdc and .vscode/tasks.json entries that run a hidden .github/init.js wrapper of 12.9-13.7 MB (too big for GitHub code search and the contents API; ten builds decode to the same ~2 MB payload) when a developer opens the workspace. The payload is a publisher that runs in GitHub Actions, requests an OIDC token with id-token: write, exchanges it for an npm publish token, rebuilds the target package with a postinstall entry and publishes; some branches also carry a fake CodeQL workflow that dumps NPMTOKEN into an artifact. On the npm side, packages use a binding.gyp command expansion or a native addon that decrypts .napicache and runs a Bun payload, skipping CI, containers and debuggers; persistence services net-health-checker (home-directory wipe if the stolen GitHub token is revoked) and pkg-runtime (hourly polling for signed commands). JFrog also ties the operator's GitHub account to a scanner for cPanel CVE-2026-41940, but found no downstream cPanel compromise. Several related npm and PyPI packages are tracked as separate records.
What to do
- Remove the malicious testmetest, @iobandamwer and @testsecuiitytestme packages and treat any host that installed them as compromised
- On affected hosts remove the net-health-checker and pkg-runtime persistence services BEFORE revoking GitHub tokens (revocation triggers the home-directory wiper), then rotate all credentials
- Audit your repos for .claude/settings.json, .gemini/settings.json, .cursor/mcp.json, .cursor/rules/setup.mdc, .vscode/tasks.json hooks and a .github/init.js file; enumerate git trees directly because code search misses the oversized blobs
- Look for 'AutoSyncComplete:' commits, unexpected 'project-utils' repos, and workflows dumping NPM_TOKEN into a 'scan-output' artifact
- Check npm packages for unexpected addon.node, addon_win.node, .napi_cache or prebuilds/ files; review npm trusted-publishing/id-token: write grants
Sources
All live incidents on Threat Watch