LIVE LOG · entries last verified against sources between October 14 and November 6, 2026 · site updated Nov 6, 2026, 2:19 PM ET

← All incidents

testmetest npm campaign planted Claude, Gemini, Cursor, VS Code hooks in 42 hijacked GitHub repos, per JFrog

Incident · npm packages and hijacked GitHub repositories · HIGH

Incident dateJul 23, 2026 (earliest smoke-test wave JFrog dates on hijacked accounts); scripted arming batches on Sep 28, 2026
DisclosedOct 26, 2026 (JFrog report on the armed GitHub repositories). SafeDep first documented the npm packages on Oct 22, 2026.
Added hereOct 27, 5:30 PM ET
Last verifiedOct 27, 2026

Summary

JFrog Security Research says the operator of the testmetest npm worm campaign armed 42 third-party GitHub repositories belonging to 11 legitimate owners. The repositories carry execution hooks in the project config files that AI coding assistants and editors read: .claude/settings.json, .gemini/settings.json, .cursor/mcp.json, .cursor/rules/setup.mdc and .vscode/tasks.json. Each hook runs a 12.9 to 13.7 MB file, .github/init.js, which JFrog says decodes to the same hidden payload, a publisher built to push more malicious npm releases. JFrog says this design turns routine developer actions, "including opening a workspace with a supported tool, into payload execution opportunities." SafeDep first documented the npm packages on Oct 22, 2026 and said then that it had found no compromised third-party packages or victims. JFrog says the payload files were large enough to slip past GitHub code search. None of the three sources we read says how many developers opened an armed repository.

Severity

HIGH High (VibeIncidents editorial rating). Per JFrog, the repositories belong to real developers and a legitimate organization, and the hooks turn routine developer actions, "including opening a workspace with a supported tool, into payload execution opportunities", so trusting an armed repository in one of those tools can be enough to start the payload. In Cursor's default setup there may be no workspace trust prompt: Cursor's security documentation says it supports workspace trust, "but it's disabled by default." The npm side of the campaign steals credentials and, per SafeDep, installs a wiper tied to the stolen GitHub token. We did not rate it Critical because none of the sources we read reports anyone who ran the payload from an armed repository.

Kit, our email provider, gets your address only to send the newsletter. Every email has an unsubscribe link. Privacy policy.

Timeline

  1. Jul 23, 2026
    JFrog says real smoke-test waves hit hijacked accounts on Jul 23 and Jul 30, 2026.
  2. Sep 28, 2026
    JFrog says the operator ran scripted arming batches across victim accounts, often copying old commit messages and author dates from legitimate history and appending skip-checks:true.
  3. Oct 21, 2026, 7:13 AM ET (11:13 UTC)
    The worm release data-pipeline-testmetest 2.0.1 is published to npm, per JFrog.
  4. Oct 22, 2026
    SafeDep publishes its analysis of the testmetest packages. It says it has found no compromised third-party packages or victims and that "All observed activity belongs to the operator's own test accounts."
  5. Oct 22, 2026, 2:52 PM ET (18:52 UTC)
    Per JFrog, a commit adds Claude, Gemini, Cursor and VS Code execution hooks together with .github/init.js to the attacker-owned repository CementBeetleSteeple/stable-scripts-9965.
  6. Oct 26, 2026
    JFrog publishes its report on the 42 armed repositories. SafeDep updates its post: the operator has moved to a third npm account and a postinstall script that loads a native Node.js addon.
  7. Oct 26, 2026, 6:29 PM ET (22:29 UTC)
    The Register reports JFrog's findings.
  8. Oct 27, 2026
    SafeDep updates its post again: a fourth account published @testsecuiitytestme/cache-helper 1.0.1 to 1.0.3, and the addon now starts the worm when an application imports the package, "so --ignore-scripts does not protect you."

How it happened

The campaign has an npm half and a GitHub half. On npm, JFrog says malicious testmetest releases ran code at install time through a binding.gyp command, without a conventional install script, and that the full worm "collected credentials, poisoned repositories and CI configuration, and propagated through package registries." SafeDep lists what the worm commits to victims' GitHub and GitLab repositories: a fake CodeQL workflow, AI agent files (.claude/settings.json, .cursor/mcp.json, CLAUDE.md, AGENTS.md, .vscode/tasks.json) and the loader .github/init.js. It says injected commits copy the author and message of the most recent real commit on the branch. The agent files are the trigger. JFrog shows the Claude hook: a SessionStart hook with matcher "*" that runs "node .github/init.js || bun .github/init.js", so the payload starts when an agent session opens in the repository. JFrog says equivalent triggers were planted for Gemini, Cursor MCP configuration and VS Code folder-open tasks, and that the payload launches detached with its output ignored "so AI-session and folder-open hooks do not block." Across the 42 repositories JFrog found 10 distinct wrapper files that all decrypt to a byte-identical 2 MB payload, a rebuild of the operator's ci.js publisher. JFrog says that publisher harvests GitHub tokens and tries to rebuild and publish a weaponized npm package through GitHub Actions. Size kept the payload out of sight. JFrog's first code search found the hooks in 26 repositories, but the .github/init.js files looked empty: "GitHub code search did not index the 12.9 to 13.7 MB blobs, and the contents API could not return files of that size." Listing each repository's Git tree raised the total to 42 armed repositories across 11 owners. JFrog describes the owners as established developers, students and a legitimate organization whose accounts or member credentials were hijacked, and in one case it says the most likely explanation is stolen collaborator access. They are victims of the campaign. JFrog says it found shared tooling with earlier worms but did not establish that the original Miasma operators are responsible.

How to check your app

Sources

Corrections and updates

  1. Oct 30, 2026
    Updated at 10:20 a.m. ET to change the severity note. We had written that opening an armed repo "can run the payload with no install step". JFrog calls routine actions such as opening a workspace "payload execution opportunities", and the note now says trusting an armed repository in one of those tools can be enough to start the payload.
  2. Oct 31, 2026
    Updated at 10:58 a.m. ET on Oct 31 to change the title from "npm worm planted" to "npm campaign planted". JFrog attributes the planted hooks to the campaign: "Within hijacked repositories, the campaign left smoke-test placeholders or armed payloads."
  3. Nov 1, 2026
    Updated at 8:34 a.m. ET on Nov 1 to add to the severity note and checklist that Cursor's security documentation says workspace trust is "disabled by default", so Cursor may show no workspace trust prompt by default before an armed repository is opened.
Cite this entry
Title
testmetest npm campaign planted Claude, Gemini, Cursor, VS Code hooks in 42 hijacked GitHub repos, per JFrog
Added
Oct 27, 2026
URL
https://vibeincidents.com/incidents/testmetest-npm-worm-ai-agent-hooks-42-repos/
Suggested citation
VibeIncidents. "testmetest npm campaign planted Claude, Gemini, Cursor, VS Code hooks in 42 hijacked GitHub repos, per JFrog." Oct 27, 2026. https://vibeincidents.com/incidents/testmetest-npm-worm-ai-agent-hooks-42-repos/