News
testmetest: 42 GitHub repositories armed for an npm worm
JFrog finds 42 armed GitHub repositories. How testmetest uses npm packages and project hooks, what has been removed and what teams should investigate.


42 third-party GitHub repositories across eleven legitimate owners: that is the scope JFrog Security Research describes for the testmetest npm worm campaign. The projects were equipped with execution paths for a hidden publisher. Alongside package installation, this brings development tools’ project configurations into focus.
A later update makes the practical question more pressing: SafeDep describes a variant in which simply importing a package starts the malware. A team that blocks installation scripts has therefore not covered every execution path.
The observation date matters. The research reports were published on 22 and 26 October; updates and revised package data have since appeared. The editorial cut-off for this article is 29 October 2026.
Key points
- JFrog reports 42 armed repositories, not 42 proven executions or affected companies.
- The campaign uses different entry points: installation, package imports and configured project hooks.
- For
@testsecuiitytestme/cache-helper, the current GitHub advisory lists 1.0.1 through 1.0.7 as affected. It does not list a patched version. - The OpenSSF record now reports this package as removed. Previously downloaded copies and credentials that may already have been exposed are not automatically remediated.
- When a compromise is confirmed, containment, investigation of persistence and the controlled replacement of credentials belong in a coordinated incident response process.
What the 42 GitHub repositories represent
The JFrog analysis published on 26 October connects npm packages with manipulated GitHub projects. In the repositories examined, the researchers found large, obfuscated files and project configurations capable of starting the hidden publisher. They identify configurations for Claude Code, Gemini CLI, Cursor and VS Code as execution paths.
The number describes a set of infrastructure findings. It does not establish how many developers actually executed the files, how many downstream users were reached or how many companies were affected. The reported overlaps in tooling also do not establish a definitive identity for the operators.
An investigation must also account for large files that can be absent from code search results. JFrog describes wrappers of around 13 MB. Searching the GitHub website alone is therefore not a complete file inventory. This does not mean that every GitHub interface is fundamentally unable to read files of that size.
Why disabling installation scripts does not cover everything
The SafeDep investigation documents several stages in the campaign’s development. These include installation paths through native build mechanisms and later native add-ons. In its 27 October update, SafeDep also describes execution when a package is loaded.
The npm option --ignore-scripts has a narrower purpose: it suppresses the relevant scripts defined in package files. It does not disable every JavaScript or native library loaded later. Explicitly invoked npm scripts also have their own rules, as the npm documentation explains.
The implication is specific: downloading a package without installation scripts and then importing it without controls is not complete isolation. Dependencies are executable code. Their subsequent use must be considered when assessing the intended environment.
The distinctions between variants should remain clear. A particular trigger belongs to particular builds that were examined; this does not mean every suspicious package contains all mechanisms at once.
Project hooks are part of a repository’s executable surface
Another entry point in testmetest lies in files that developers often regard as tool configuration: for example, .claude/settings.json, .cursor/mcp.json or .vscode/tasks.json. An unfamiliar command there deserves the same review as an unfamiliar build script.
The Claude Code documentation describes hooks as event-driven automation. Depending on the hook type, they can execute commands. This explains the fundamental difference from a note in a repository: a configuration can cause a process to start.
Whether an armed project can use this path on a particular machine depends on the tool version, configuration and trust granted. VS Code Workspace Trust, for example, limits tasks and other features in Restricted Mode. The report does not establish a universal bypass of all trust dialogs.
Our assessment: security reviews should include the tools used to open and work on a project. This includes approved project hooks, tasks and MCP server configurations. A malicious process can start without a language model first having to be persuaded by a prompt.
This report therefore concerns a different mechanism from the AISI test involving an AI agent acting without authorization: the issue here is malicious software and execution paths in the development tool environment.
What is known about package versions on 29 October
Older reports cannot be carried forward unchanged as the current registry state. The OpenSSF record MAL-2026-18358 was updated on 29 October. For @testsecuiitytestme/cache-helper, it lists 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6 and 1.0.7 as affected and records the removal of the entire package on 27 October at 22:17 UTC.
The GitHub advisory GHSA-4g45-28rv-vq9q lists the same seven versions and no patched version. Its description still contains the earlier observation about version 1.0.3. The updated version list and the dated OpenSSF entry are the relevant references for the current assessment.
SafeDep’s original statement that it had not found third-party victims is also explicitly tied to 22 October. It does not contradict the GitHub findings JFrog published later.
Removal prevents further regular downloads through this registry publication. It does not remove an existing copy from a developer’s machine, cache, mirror or build artifact. Nor does it invalidate a token that has already been stolen. These distinctions determine what an affected organization still needs to investigate.
What teams can investigate now
The first question is whether an affected component was actually present in the organization’s software inventory. Existing lockfiles, software inventories and stored package metadata can help answer it. Package name and version belong together; a harmless placeholder version does not automatically represent the same finding as a malicious release.
To narrow the investigation, teams should document three areas separately:
| Area | Question to resolve | Suitable existing records |
|---|---|---|
| Dependencies | Which specific version was downloaded or used, and when? | Lockfiles, package inventories, build logs and cache metadata |
| Development environment | Which project hooks or tasks could execute? | Approved configurations, changes and available process events |
| Publishing | Which repositories, workflows and credentials were accessible? | Audit logs, workflow histories, token permissions and release data |
The published indicators provide starting points for this investigation. A matching filename alone does not prove a compromise. Conversely, a search with no results does not end the investigation if relevant files or time periods were never covered.
Do not open suspicious projects for inspection in an ordinary development environment that could start their automation. Use an appropriate isolated analysis process. Investigating the case does not require installing the named malware as a test.
A confirmed compromise requires a coordinated response
The research reports describe a wiper in examined payloads: a deletion function that can react to the revocation of a stolen GitHub token. A blanket instruction to “revoke tokens first, then investigate the machine” would therefore be incomplete for this case.
Bring in your incident response team when there is credible suspicion: contain affected systems and automated processes, preserve relevant evidence, address active malicious processes and persistence, or plan a controlled rebuild. Coordinate the prompt revocation and replacement of endangered credentials with these steps, using a trusted administration environment.
This is not a recommendation to leave stolen credentials usable. Containment and credential recovery need to work together. The accounts and systems included in recovery depend on the permissions and data that were actually accessible, not just the package name.
Record the version found, whether execution is evidenced, which services could be affected and what work remains open. Removing a file and restoring trust are different outcomes.
Implications for the regular release process
For npm publishers, separating development work from publishing authority is particularly important. Trusted publishing with OIDC can replace long-lived publishing tokens with short-lived permissions bound to a workflow, where supported. This removes a particular form of permanently stored publishing access.
That benefit depends on a protected publishing process. If untrusted code runs in a privileged release job, the job’s authority remains relevant. The GitHub recommendations for Actions therefore address least privilege, handling untrusted code and securing the actions in use, among other topics.
For companies that do not publish npm packages themselves, the inventory question remains: which dependencies, development tools and build services belong to which product or service? And who owns the follow-up investigation when a finding becomes known?
Kopexa can connect this work with affected assets, risks, measures, owners and evidence. Technical detection and remediation remain the responsibility of the tools and specialists used for those tasks. This keeps investigation and follow-up traceable when development, operations and information security work together.
The connection that matters
testmetest connects package downloads, local development tools and publishing paths. The report is therefore more than a list of removed npm versions: teams need to establish which code executed in which context and what further access it could have enabled.
The current version information helps narrow the scope. Whether execution or access occurred in a particular company must be established by its own investigation. Keeping those questions separate turns a news report into a defensible task for the organization.
Quick answers
Frequently Asked Questions
Still have a question? Find the answers here.
What do the 42 GitHub repositories in testmetest represent?
JFrog describes 42 third-party repositories across eleven legitimate owners that were equipped with execution paths for a hidden publisher. This number is not a statistic covering 42 proven executions, infected companies or downstream victims.
Does npm --ignore-scripts protect against every testmetest variant?
No. The option limits the execution of certain package scripts. SafeDep’s 27 October update also describes a variant that starts when a package is imported. The installation option does not generally disable application code loaded later. The affected version and its execution path need to be assessed separately.
Is this a vulnerability in Claude Code or VS Code?
The report describes abused project configurations and hooks as execution paths. It does not establish a universal vulnerability that bypasses every tool version or trust setting. VS Code, for example, limits tasks in Restricted Mode. Assessment depends on the specific configuration, trust granted and possible execution.
Is the risk resolved once the npm package is removed?
No. The OpenSSF record reports @testsecuiitytestme/cache-helper as removed on 27 October and lists versions 1.0.1 through 1.0.7 as affected on 29 October. Existing local copies, mirrors, caches or artifacts do not disappear as a result. Credentials that may already be exposed and manipulated repositories require separate treatment.
Why must token revocation be coordinated with remediation?
The researchers describe a deletion function in examined payloads that can react to revocation of a stolen GitHub token. In a confirmed compromise, containment, treatment of malicious processes and persistence, and the prompt revocation and replacement of endangered credentials must be coordinated. New credentials belong in a trusted environment, not on a machine that remains compromised.
Does a package name or hook file alone prove a compromise?
No. Package names, versions, file contents and evidence of execution need to be assessed together. Legitimate projects also use hooks and tasks; npm’s placeholder version is not itself evidence of malware. Published indicators help narrow the scope, but do not replace an investigation of the organization’s own software inventory and accessible systems.
Sources
- JFrog: Beyond testmetest – 42 Armed GitHub Repositories () [Accessed ]
- SafeDep: testmetest npm Packages Carry a Miasma-Family Worm () [Accessed ]
- OpenSSF: MAL-2026-18358, as of 29 October 2026 [Accessed ]
- GitHub Advisory Database: GHSA-4g45-28rv-vq9q [Accessed ]
- npm CLI: ignore-scripts [Accessed ]
- Claude Code: Hooks reference [Accessed ]
- Visual Studio Code: Workspace Trust [Accessed ]
- npm: Trusted publishing for npm packages [Accessed ]
- GitHub Actions: Secure use reference [Accessed ]