keyv/cacheable npm worm plants Claude Code and VS Code hook files as an AI-agent execution vector
Real-world incident04 Aug 2026🗺️ Tool-Using AgentA self-propagating npm worm reportedly hijacked the keyv/cacheable maintainer account and trojanized hundreds of package versions with a malicious preinstall hook, and additionally committed Claude Code and VS Code hook files into the source repo so that merely opening a checkout in an AI-enabled IDE runs the payload with no npm install.
Root cause — why it happened
Developers install open-source packages by the millions and trust that a popular, long-established one is safe. Attackers stole the account of the person who maintains a very widely used set of npm packages and quietly poisoned hundreds of versions. Two traps were laid. The first is old: a package can run a little script the moment you install it. The second is new: the attacker also slipped in the small setup files that AI coding assistants automatically run when you simply OPEN the project — so you didn't even have to install anything. Security scanners look at the package's install scripts; almost none look at an AI assistant's hidden setup files, so the trap sat in a place nobody checks.
Risks this case illustrates
Named in the standard (OWASP/ATLAS/NIST) lens. Click a highlighted component in the diagram below to see which risks attach where.
How it unfolded
A developer working inside an AI-enabled IDE
A developer uses an AI coding assistant built into their editor. As a convenience, the assistant automatically runs a project's small setup hooks when the project is opened, so it's ready to help right away. That auto-run convenience is what everyone is trusting to be harmless.
Controls & guardrails — what would have stopped it
The trap needed two things: a poisoned package to reach the developer, and an AI assistant willing to run the package's setup files automatically. Break either. Verify where each package version really came from so the poisoned ones are caught, and don't let the AI assistant auto-run setup files that arrived inside a downloaded project without a person approving. Then run installs in a locked box and give build logins only tiny, short-lived powers — so even a payload that runs steals little and can't spread.
- MCP/plugin pinning, manifest hashing & re-review
Review catches what reviewers understand; a subtle malicious directive can pass. Pinning helps only if you actually re-review on update rather than auto-accepting.
- Tool argument validation & sandboxing
Validates form, not intent — a well-formed call to a permitted tool can still be the wrong call. Sandboxing adds latency and isn't always feasible for tools that touch production.
- Least-privilege identity & scoped credentials
Doesn't prevent manipulation — only caps its reach. Hard to get right operationally; over-broad scopes are the common real-world failure.
- Egress allowlisting & DLP on tool arguments
Allowlists fight an open-ended channel; legitimate-but-broad destinations (any URL fetch, any email) are hard to constrain without breaking usefulness. Encoding can evade naive DLP.
- Per-agent identity & taint-marked messages
Adds coordination overhead and doesn't stop a worker from returning subtly wrong (but well-formed) results that mislead the planner.
- Runtime monitoring & anomaly detection
Detects the anomalous, not the novel-but-subtle; high false-positive rates cause alert fatigue. Always a step behind a sufficiently quiet attacker.
- Full-trace audit logging
Logging is forensic, not preventive — it explains harm after the fact. Useless if no one reviews it or if the materialised context isn't captured.
- Governance: risk assessment, red-teaming & incident responseaddressesSupply-Chain Compromise
Process reduces likelihood and speeds recovery but executes no technical control itself; weak follow-through makes it theatre.
- Loop/cost circuit-breakers & consistency checks
Thresholds are blunt — too tight breaks legitimate long tasks, too loose lets damage accrue first. Catches runaway dynamics, not a single well-formed bad decision.
Lessons
- ▸ AI-agent hook/config files (`.claude`, IDE tasks) are an autorun surface: if an attacker can commit them into a dependency, opening the checkout runs their code — no `npm install` needed.
- ▸ `--ignore-scripts` only governs the npm lifecycle path; it does nothing for the agent-hook path that fires on repo-open, so the two surfaces need separate controls.
- ▸ Dependency scanners and reviewers model `package.json` scripts, not agent config — committed hook files hide malware in a trusted-but-unmonitored location.
- ▸ Trust anchored to a package's name and download count is not provenance; verify each version's origin (lockfiles, integrity hashes, signed releases).
- ▸ Least-privilege, short-lived CI/cloud credentials plus egress control both cap the blast radius and deny a credential-worm the publish rights it needs to spread.
Proposals & gaps this case surfaced
Non-destructive suggestions for the library — proposed, not adopted.
A supply-chain code-execution vector in which an attacker commits AI-agent hook/config files (e.g. Claude Code `.claude` hooks, VS Code task/hook files) into a package or repository, so that a developer's AI-enabled IDE or coding agent auto-executes the payload on repo-open — with the developer's ambient privileges, no `npm install`, and no approval prompt. It is distinct from a poisoned package lifecycle script (`preinstall`/`postinstall`) because it fires outside the package-manager lifecycle, defeating `--ignore-scripts` and install-time sandboxing, and it hides in a path (agent config) that dependency scanners and code review typically do not inspect.
Treat every autorun surface an AI coding agent honours as attacker-populatable, and cover both the package lifecycle and the agent-hook path. (1) Do not auto-execute project-scoped agent hook/config files (`.claude/settings*.json` hooks, VS Code tasks) from an untrusted workspace on repo-open — require explicit developer consent, or restrict auto-run to an allowlist of vetted repositories. (2) Bring agent hook/config files into SCA and code-review scope so they are inspected like `package.json` scripts (they are code, not just settings). (3) On the supply-chain side, pin and verify dependency provenance (lockfiles, integrity hashes, signed releases) and install with scripts suppressed (`--ignore-scripts`) inside a sandbox — noting this does NOT cover the repo-open hook path, which needs control (1). (4) Scope CI/cloud credentials to least privilege with short-lived tokens and egress allow-listing, so a payload that does run cannot harvest broadly, move laterally, or reuse publish rights to propagate. Closes the keyv-worm vector where committed agent-hook files execute on checkout-open; distinct from lifecycle-script mitigations, which the agent-hook path bypasses.
This case shows a blind spot: we scan a package's install scripts for malware, but almost nobody scans the AI assistant's setup files — even though the assistant runs them automatically when you open a project. An attacker who hides code in those files gets a free run. Reviews and scanners should read AI-agent config the same way they read install scripts.
These surface as proposals across the Control Library and Risk Taxonomy; adopt them by hand when ready.
Sources
- Snyk ↗
- Wiz ↗
- Snyk — Inside the keyv npm supply-chain compromise: preinstall malware, trusted provenance, IDE hooks ↗ — Primary write-up; details the committed IDE/agent hook-file execution vector alongside the preinstall hook.
- Wiz — keyv and cacheable npm supply-chain attack ↗ — Scope of the namespace compromise and the credential-harvesting payload.
- Socket — Popular npm packages in the keyv and cacheable namespaces compromised in active supply-chain attack ↗ — Version counts and install volumes (as reported).
- Datadog Security Labs — Worm compromises hundreds of popular npm packages ↗ — Worm propagation mechanics (the 'mini Shai-Hulud' credential-republish loop).
- OWASP LLM03:2025 — Supply Chain ↗ — Framework mapping: supply-chain risk for LLM/agent application stacks.
Practise the risk class — related scenarios
A coding agent asks to write ./notes.txt — the file it actually overwrites is your SSH keys
A text-to-SQL agent runs the model's output straight at the database
Compromise the pipeline that builds agents, and every new worker is born malicious
An auto-approving coding agent reads a poisoned page — and executes code it never should have
A fake Sentry error report hijacks a developer's coding agent into running a shell command
Every command is harmless on its own — the sequence is the exploit
A 'safe' dataset preview turns an upload into code execution on the pipeline's workers
A cost-saving open-weights swap quietly ships a model with its safety surgically removed
A capable third-party model that behaves perfectly — until it sees the trigger
A trusted MCP email tool quietly BCCs every message to an attacker