Post

Don't Revoke That Token Yet Inside the keyv/cacheable npm Worm

Don't Revoke That Token Yet Inside the keyv/cacheable npm Worm

Don’t Revoke That Token Yet: Inside the keyv/cacheable npm Worm

In the keyv/cacheable compromise that has been unfolding since yesterday, it is the one thing you should not do first – because revoking the stolen token is exactly what arms the payload. On August 4, 2026, an attacker took over the maintainer account behind the widely used keyv and cacheable npm namespaces – caching libraries that sit near the bottom of a very large number of dependency trees – and published trojanized releases. Socket’s Threat Research team, which did the primary analysis, places the first malicious release, [email protected], at 09:35 UTC. The poisoned versions ship a preinstall hook: “scripts”: { “preinstall”: “node setup.mjs” }. setup.mjs downloads a standalone Bun runtime, runs an obfuscated second stage (Math_Symbol.js, ~728 KB), and harvests whatever it can reach: AWS instance metadata, cloud keys, Vault tokens, Kubernetes service-account tokens, GitHub Actions secrets, npm tokens, and private keys and bearer tokens on disk. Then, it uses the stolen npm token to inject the same hook into other packages the compromised identity can publish, recomputes the integrity hashes, and republishes. It is a worm. The public IOC lists now cover more than 440 packages across two thousand-plus versions, and they are still moving.

Two properties make this one worth a closer look than the average typosquat. Most teams scope this kind of incident to “who ran npm install in the exposure window.” That misses half the population. The source repository also received IDE and agent autostart hooks – a SessionStart entry in .claude/settings.json and a folderOpen task in .vscode/tasks.json – that run the loader when the cloned folder is simply opened. No install, nothing built. A checked-out repository is now an execution surface, and .claude/, .cursor/, and .vscode/ are part of it. Alongside the credential theft, the payload installs a host-level dead-man’s switch. It writes the stolen GitHub token and an attacker-supplied handler command to ~/.config/gh-token-monitor/, then persists itself as a macOS LaunchAgent or a Linux systemd user service with loginctl enable-linger so it survives logout. A watcher script polls the GitHub API with the stolen token every 60 seconds. While the token works, nothing happens. The moment the token stops working – an HTTP 4xx, which is precisely what your revocation produces – it evals the remote-supplied handler string, then deletes its own state and exits. Public analysis cannot say what is in the handler, because it is attacker-controlled text pulled at runtime and can be changed remotely. It could be data destruction, re-implant, or nothing at all.

One consequence is counterintuitive but load-bearing: isolating the host from the network is safe. With no connectivity there is no HTTP response, so there is no 4xx, so the switch does not fire – and exfiltration stops at the same time. Isolate first. Do not power off; volatile memory is evidence. The order matters more than the individual steps: Isolate the host from the network. Do not shut it down. Preserve evidence before you delete anything – the watcher self-clears in ~24 hours. Copy ~/.config/gh-token-monitor/{handler,token,started_at}, the payloads, the plist/unit, and record hashes. Do not execute the handler; treat it as inert text. Eradicate: kill the watcher, unload the LaunchAgent / disable the systemd unit, drop loginctl linger, remove the files and the .claude/.vscode hooks, and clear the package caches. Rotate – now, and only now. npm token first, to stop propagation; then GitHub, cloud, Vault, Kubernetes, CI secrets, and anything that was sitting in a file, because there was a regex sweep. Revoke, do not merely rotate. CI runners and any host with confirmed execution should be rebuilt, not cleaned.

The novel part of this campaign is not the credential theft – it is the two design choices around it: an execution path that does not require installing anything, and a switch that turns your remediation reflex into the trigger. Scope the second vector, isolate before you revoke, and clean the host before you touch a single token.

Read full article

This post is licensed under CC BY 4.0 by the author.