JFrog says the 'testmetest' npm worm campaign had already armed 42 GitHub repositories belonging to 11 legitimate owners, using 12.9 to 13.7 MB payload files that exceed the practical size limits of GitHub code search, and has moved to native Node add-ons that stay dormant in CI and sandboxes
JFrog Security Research said on 26 October 2026 that it found 42 armed third-party GitHub repositories across 11 legitimate owners connected to the 'testmetest' npm campaign.
JFrog says the repositories carry execution hooks for AI coding assistants and IDEs (its remediation list names Claude, Gemini, Cursor and VS Code settings files), plus polymorphic wrappers of 12.9 to 13.7 MB that all decode to the same hidden CI-publisher payload, built to run through GitHub Actions and use npm tokens or trusted publishing to produce further malicious releases.
JFrog says the wrappers exceed the practical size limits of GitHub code search and the contents API, so defenders should enumerate repository trees directly, and that by 28 September the campaign had armed real repositories belonging to established developers, students and a legitimate organisation.
SafeDep, which first documented the npm side on 22 October, reported at the time that it had not confirmed compromised third-party packages or victims; JFrog says its GitHub analysis reaches a different conclusion.
JFrog says the npm worm stole GitHub and npm credentials that could give access to third-party repositories, and that it contains a wiper triggered when the stolen GitHub token is revoked. In later packages (@iobandamwer/cache-helper, @iobandamwer/native-helper and path-stream-utils-testmetest) the operator shipped a precompiled Node add-on, called by a one-line postinstall, that decrypts a hidden .napi_cache file to reveal the real payload; JFrog says it fires on real developer laptops and servers but stays asleep in the CI runners, containers and sandboxes used by package scanners, and stops if a debugger is attached.
JFrog says the add-on variant is tied to the rest of the campaign through the GitHub account CementBeetleSteeple, and links the campaign, through shellpanel artifacts in the same hijacked owner cluster, to GitHub Actions workflows that scanned for and tried to exploit the cPanel and WHM authentication bypass CVE-2026-41940, but says it found no evidence of successful downstream cPanel compromises. Primary: JFrog; wire: The Register.
- Product
- npm packages in the testmetest campaign (including event-bus-lite-testmetest, @iobandamwer/cache-helper, @iobandamwer/native-helper, path-stream-utils-testmetest) and hijacked GitHub repositories
- Versions
- Malicious releases of 14 npm packages listed by JFrog (for example data-pipeline-testmetest, event-bus-lite-testmetest, log-rotate-testmetest, retry-utils-testmetest, @iobandamwer/cache-helper, @iobandamwer/native-helper, path-stream-utils-testmetest)
- Exploited in Australia?
- unknown
- Patch to
- Check lockfiles and build caches for the 14 packages JFrog lists and treat installing a full-worm version as a host compromise. Following JFrog's order: remove the net-health-checker and pkg-runtime persistence (LaunchAgents, systemd user services) before revoking the stolen GitHub token, because the worm carries a token-revocation wiper; then revoke and rotate GitHub, npm, PyPI, cloud, SSH and AI-provider credentials. Audit repositories for .github/init.js, .claude/settings.json, .gemini/settings.json, .cursor/mcp.json, .cursor/rules/setup.mdc and .vscode/tasks.json hooks, chore/ci-* and deps/upd-* branches and skip-checks:true commits, enumerating repository trees directly rather than relying on GitHub code search. Be wary of packages whose postinstall runs a native .node add-on with a hidden .napi_cache file. Patch cPanel and WHM for CVE-2026-41940.
