Skip to content
Software Supply Chain Security

NPM worm in Keyv: credential theft and VS Code hooks

npm-worm Keyv

A recently confirmed NPM worm in Keyv targeted JavaScript development workflows by stealing credentials and using automated publishing access to poison packages across the npm registry. The campaign began with keyv@6.0.0 on August 4, 2026, then expanded into hundreds of package names spanning multiple organizations.

Security monitoring by SafeDep counted dozens of poisoned versions within a large set of affected packages, while Aikido later reported an even broader reach. The reports agree on the core risk: any workstation or CI runner that installed an affected dependency should be treated as credential-exposed, not merely as having fetched a suspicious file.

How the NPM worm in Keyv spreads through npm

The malicious release relied on npm lifecycle behavior. Specifically, the infected package used a preinstall script to run a credential-stealing bundle inside both developer machines and continuous integration (CI) environments.

SafeDep’s analysis describes a payload that can harvest multiple kinds of sensitive material, including repository data, package registry credentials, cloud secrets, and private keys. After collecting information, the worm also uses available npm publishing access to poison additional packages, turning one compromised pathway into a wider supply-chain infection.

Because registry updates happen quickly, the campaign could not be reliably mapped by a single fixed “latest tags” list. Instead, responders are advised to validate exact package names, resolved versions, and lockfiles to understand what was actually installed.

What SafeDep and Aikido found in the poisoned package footprint

SafeDep verified 353 poisoned versions across 79 package names in the npm registry. Its monitoring then indicated a wider footprint of 442 versions across 353 names. Later, Aikido reported at least 868 packages across 1,381 versions.

It’s important to interpret these totals correctly. The counts refer to malicious package artifacts, not the number of victim systems that actually executed them. In other words: campaign scale can be large while the number of compromised machines depends on whether the affected versions were installed and whether lifecycle scripts ran.

Why CI and developer environments were at risk

The worm’s preinstall execution means the sensitive activity can occur at install time. That matters for CI pipelines, where dependencies are often installed automatically during builds.

The reports also highlight that editor and workspace hooks were available through the repository itself. For teams using VS Code or Claude Code, trust settings can determine whether those hooks later activate.

Payload capabilities: harvesting and republishing

SafeDep’s payload analysis indicates that the bundle targets a wide range of sources and secret stores. It describes harvesting data related to GitHub, npm credentials, cloud configuration, Vault, Kubernetes, database materials, and private keys.

Beyond collection, the malware installs a token-revocation watcher and includes npm publishing machinery. Socket’s separate decoding further indicates it could modify, version, and republish packages available to a stolen npm identity—supporting the observation that the campaign expanded rapidly.

Notably, the evidence does not prove whether one stolen publisher identity drove all propagation, or whether multiple publishing credentials were compromised independently. That uncertainty affects attribution, but it doesn’t reduce the operational remediation need.

Keyv@6.0.0 details: what changed in the first malicious release

The first confirmed malicious release was keyv@6.0.0. According to the report, it added node setup.mjs as a preinstall command. The package included setup.mjs and Math_Symbol.js, while leaving the compiled library code unchanged.

The stage-one logic checks for the Bun runtime. If Bun isn’t present, it downloads Bun 1.3.13 from the runtime’s official GitHub releases and then hands off to a compiled bundle roughly 727,680 bytes in size.

Editor hooks: Claude Code and VS Code execution paths

In addition to npm lifecycle execution, the Keyv repository retained separate hooks for Claude Code and Visual Studio Code (VS Code). These hooks can execute the payload when a user trusts the workspace or permits project configuration.

SafeDep and Socket describe a path through repository configuration files. For Claude Code, .claude/settings.json contains a SessionStart hook that calls .vscode/setup.mjs. For VS Code, .vscode/tasks.json includes an “Environment Setup” task configured with runOn: folderOpen that calls .claude/setup.mjs.

However, these triggers are not guaranteed to run in every default environment. VS Code blocks automatic tasks in untrusted workspaces and prompts before allowing them by default. Claude Code can apply workspace trust based on how project settings are handled.

Why “rotate first” can backfire

A key remediation warning centers on the worm’s credential-revocation watcher. The report explains that revocation is the trigger. If defenders rotate exposed tokens and keys first, the attacker-supplied local handler may run.

SafeDep’s guidance advises responders to remove the malware’s credential-revocation watcher before rotating any exposed credentials. The goal is to prevent the malicious component from reacting to changes intended to cut off access.

It also notes that npm 12 blocks unapproved dependency lifecycle scripts by default. Earlier npm clients—or other installation paths that allow lifecycle scripts—remain exposed.

Registry “latest” may change—so trust lockfiles and resolutions

The worm’s campaign affected “latest” tagging as packages were restored or retagged. At 5:40 p.m. IST on August 4, at least nine packages from the initial poisoned set appeared with earlier releases restored as latest, including versions such as keyv@5.6.0, flat-cache@6.1.23, and cache-manager@7.2.9.

Because tags can change and not every related package was poisoned, building exposure checks based on namespace-level blocklists can create two failure modes: missing poisoned versions and wrongly treating unaffected releases as compromised.

Instead, teams should check what was actually installed, using exact dependency versions and the relevant lockfiles from their build artifacts.

Second execution path in the repository tree

The repository also appears to have carried a second route for execution. A later commit staged payload files across all 19 workspace packages. That detail matters because a release cut from a poisoned tree could distribute the payload even if some specific packages were not directly tagged in the initial analysis.

The report further notes that some adapter packages in the @keyv/* scope and the Keyv 5.x line were reportedly clean. Still, the existence of multiple staging paths reinforces why lockfile-based verification is essential.

Connections to earlier malware patterns

Semgrep documentation links the same Claude Code and VS Code hook structure, including the setup.mjs filename and the Bun 1.3.13 download, to a prior compromise involving the “lightning” PyPI package (described as an April compromise).

Aikido places the August activity within the Shai-Hulud family, supporting a malware-family connection. While the overlap suggests related tooling and technique reuse, it does not identify who operated the campaign or how the attacker initially gained access.

What teams should do now

If your systems installed the NPM worm in Keyv, treat them as credential-exposed until proven otherwise. The report emphasizes using exact package names and resolved versions rather than relying on “currently latest” tags.

In practice, incident response should focus on three steps: determine whether affected versions were installed on developer machines and CI runners; remove the watcher component described in the analysis; and only then rotate any tokens and keys that might have been exposed.

Finally, review editor trust and workspace configuration policies. Editor hooks can add an additional trigger surface beyond npm lifecycle scripts, particularly when a workspace is trusted or task execution is permitted.

Conclusion

The NPM worm in Keyv shows how quickly supply-chain attacks can scale when malicious code runs during dependency installation and then leverages publishing access to poison additional packages. The campaign also introduced editor hooks that can activate based on trust and workspace permissions, extending the risk beyond CI pipelines.

With registry tags changing during and after the event, the safest approach is to audit what your environment actually installed—using lockfiles and resolved versions—then remediate in the correct order to avoid triggering the malware’s revocation-triggered behavior.

Source: https://thehackernews.com/2026/08/keyv-linked-npm-worm-poisons-hundreds.html