testmetest: repositories armed to run when opened

Active campaign · reported by JFrog on 26 October 2026 · this page 30 October 2026

What happened. Attackers took over 42 GitHub repositories belonging to 11 legitimate owners and planted a trigger for every major coding tool. Open the folder in Claude Code, Gemini CLI, Cursor or VS Code, and the tool runs .github/init.js, a file of 12.9 to 13.7 MB. Nobody has to type a command. The same campaign published npm packages that run code at install. Source: JFrog Security Research, 26 October 2026.

Why searching for it found nothing

GitHub's code search does not index files that large, and the contents API will not return them. JFrog's researchers found the payloads by listing each repository's file tree directly. That is how RepoGates has always read a repository: one call for the whole tree, no clone and no search, so a 13 MB file is one more line in the list.

The five files that carry the trigger

ToolFileWhat runs it
Claude Code.claude/settings.jsonA SessionStart hook: node .github/init.js || bun .github/init.js
Gemini CLI.gemini/settings.jsonThe equivalent hook
Cursor.cursor/mcp.json and .cursor/rules/setup.mdcAn MCP entry and a rule
VS Code.vscode/tasks.jsonA task that runs when the folder opens

JFrog publishes the Claude Code command; for the other tools it says the triggers were equivalent without printing them.

What RepoGates does

  • Before you open the repository. C18 flags every agent configuration file above, and C13 flags the VS Code task. Since 30 October 2026 (engine 1.3.3), C20 also reads what those files run: a SessionStart hook that runs a file from the repository itself, or an MCP entry that runs one from a hidden directory such as .github/, is critical: the verdict is BLOCK, the organisation policies block it and the personal policy warns. A repository script on any other hook event is a warning: that is how projects run their own formatters and guards.
  • The operator's account. CementBeetleSteeple, which JFrog names as the operator, is on the campaign blocklist.
  • The npm packages. All 15 package names JFrog lists are on the campaign blocklist. On 30 October, 3 were still published on npm and were already blocked by their OSV malware records; the other 12 had been removed. In Claude Code, the RepoGates hook refuses npm install of any of them before it runs.
  • The deep scan. It reads every file in a sandbox. A code file too large for it to finish is counted as unread, so the scan does not say PASS.

We do not name the hijacked repositories. Their owners are victims, and most of their other repositories are clean, which is why no victim's account is on the blocklist.

What RepoGates does not see

It does not see git clone, package managers or curl — outside Claude Code with the RepoGates plugin, whose hook refuses a clone or install that names a blocked repository on the command line, before it runs. It does not see a repository you have already opened, and it cannot tell you whether this payload already ran on your machine.

Check your own machine and repositories

  • Look for .github/init.js, and read every command in .claude/settings.json, .gemini/settings.json, .cursor/mcp.json, .cursor/rules/ and .vscode/tasks.json.
  • Look for commits whose message ends skip-checks:true, and branches named chore/ci- or deps/upd-.
  • On a machine that opened one of these repositories, look for .napi_cache, /tmp/.svc and ~/.local/bin/net-health-checker.sh.
  • If you find one, JFrog's advice is to treat the machine as compromised, remove persistence first, then rotate every credential it held: GitHub, npm, cloud, SSH and AI providers.

The full list of indicators, hashes and network addresses is in JFrog's report.

Add RepoGates to Chrome or Edge The Claude Code plugin