Back Techtimes keyv npm Supply Chain Attack Hides Malware in AI Agent Files Scanners Never Read
On August 4, 2026, the Shai-Hulud npm worm returned for its sixth major campaign since September 2025 — and for the first time, it introduced three capabilities that no prior wave had shipped: executable payloads planted inside AI coding agent and IDE configuration files that no dependency scanner reads, a command-and-control layer that routes through an Ethereum smart contract rather than a hardcoded domain, and a token revocation watcher that triggers attacker-controlled code the moment a defender tries to rotate stolen credentials. Every JavaScript and Node.js developer who installed a caching library on August 4 — or simply opened the keyv repository in VS Code or Claude Code — needs to act on the sequenced response guidance below before touching credentials.
The attack began when an attacker who had compromised the GitHub account of jaredwray — the maintainer behind the keyv key-value storage library — pushed malicious files to the repository's main branch at approximately 5:00 a.m. ET on August 4. Four minutes later, a verified commit added the Claude Code and VS Code persistence hooks. By 5:35 a.m. ET, [email protected] had landed on the npm registry carrying a valid OIDC provenance attestation and a Supply-chain Levels for Software Artifacts (SLSA) signature — every cryptographic signal that the industry spent years building pointed to a legitimate release, as Snyk's independent analysis confirmed. By midday, Aikido Security had counted more than 434 compromised packages representing over two billion combined monthly downloads, per Aikido Security's tracking .
Keyv is no niche library. The package records roughly 127 million weekly downloads, and the same maintainer controls a cluster of related caching utilities that collectively dwarf even that number. Kodem Security's analysis of the eleven confirmed seed packages shows the full scale of the single-maintainer exposure.
flat-cache and file-entry-cache each carry roughly 565–580 million monthly downloads — figures that put them among the most-downloaded packages in the npm registry. cacheable-request adds 137 million monthly downloads. cacheable , @cacheable/memory , cache-manager , @cacheable/node-cache , @cacheable/utils , @cacheable/net , and ecto complete the poisoned set, per the Kodem Security Wave Six runbook . The worm then used stolen npm publishing tokens to spread into hundreds of additional packages across at least nine organizations, including @servicetitan , @or-sdk , @onereach , @ornikar , @qlik , @nebula.js , @hubsync , Picsart, and Deliveroo.
The malicious release buried its destructive capability inside a preinstall lifecycle hook — a script npm executes automatically before a package finishes installing, without any user interaction or visible warning. Kodem's analysis traced the execution path across two stages, documented in their first-hour response runbook .
The first stage checked the victim system for the Bun JavaScript runtime. If absent, it downloaded Bun version 1.3.13 directly from Bun's official GitHub releases page — a legitimate destination that evades domain-based blocklists — then handed execution to a 727,680-byte obfuscated second-stage bundle named Math_Symbol.js .
The second stage was the operational core. Aikido's payload analysis found that the bundle swept an extraordinarily broad set of credentials: npm publishing tokens, GitHub personal access tokens and OAuth tokens, GitHub Actions runner memory targeting OIDC tokens used for npm publishing, AWS credentials including the EC2 instance metadata endpoint at 169.254.169.254 , Kubernetes configuration files and service account tokens, HashiCorp Vault tokens, Stripe and Slack keys, and a TruffleHog-style regex sweep across roughly 200 file patterns targeting .env files, SSH keys, Terraform state, Docker registry credentials, and IDE configuration files, as detailed in Aikido's full payload breakdown . The Wave Six build expanded credential targets by nearly 70% over prior waves, adding AI agent credential stores for Claude, OpenAI, Codex, Cursor, and Gemini; cryptocurrency keystores for Foundry, Solana, and Monero; self-hosted CI and registry secrets including Jenkins' master.key , Argo CD, and Harbor; and Alibaba Cloud and Tencent Cloud configurations, according to Wiz Research's Wave Six analysis .
Exfiltrated data was encrypted with the attacker's RSA public key before being committed to public GitHub repositories created under compromised identities, each bearing the description "Shai-Hulud: Here We Go Again." Aikido observed roughly 1,300 such repositories created on August 4 alone — an encrypted trove visible to the public but readable only by whoever holds the attacker's private key.
Every prior Shai-Hulud wave executed through the npm install lifecycle. Wave Six added a secondary execution path — and it is the one that most security teams are not monitoring.
The attacker embedded two hook files directly in the keyv repository for anyone who had cloned the project. The repository's .claude/settings.json file contained a SessionStart hook pointing to a loader script. A separate .vscode/tasks.json carried an "Environment Setup" task configured with "runOn": "folderOpen" — meaning the loader fires when a developer or CI system opens the project directory in VS Code, with no package installation required, as documented in Kodem's detailed persistence breakdown .
The commits introducing these hooks were authored as [email protected] with the commit message chore: update config — a message that blends into ordinary automated maintenance activity. The commit even carried GitHub's green "verified" badge.
Both VS Code and Claude Code apply workspace trust controls that require user approval before running such tasks automatically. But as Kodem's analysis observed, the structural significance of the technique goes beyond any individual attack: "Agent configuration files execute code, they live in repositories, and no dependency scanner reads them." The worm's propagation mechanism also weaponized this vector — using stolen GitHub tokens, it committed .claude/settings.json and .vscode/tasks.json hooks into every branch it could reach across victim repositories, up to 50 branches per repo, so that any developer who later opened any of those repositories would encounter the execution path.
Kodem predicts the wave will target agent configuration formats beyond Claude Code and VS Code, specifically MCP server definitions and editor-level agent rule files, because those execute with the same trust level and currently receive even less review than package.json .
Shai-Hulud waves hardcoded a domain or IP address as their command-and-control (C2) infrastructure — configurations that defenders could block once identified. Wave Six replaced that model with an Ethereum smart contract.
Wiz Research identified the malware querying a StringListStore contract at address 0xE1f2395ee43e45A1556EC6438a88c31B83493103 using an eth_call RPC call to retrieve the current C2 domain, per Wiz's smart contract C2 analysis . On-chain history showed the contract was initially configured with three domains before being updated to return only npm-cache[.]com — a domain registered on May 22, 2026, that serves no legitimate purpose. The contract owner was funded by an address previously flagged as associated with scam activity.
The operational significance is structural. A defender who blocks npm-cache[.]com has not neutralized the C2 — the attacker can update the smart contract to point to a new domain at any time, requiring no modification to the payload. The payload on disk does not need to change at all. The malware queries the Ethereum RPC endpoint, reads the current domain value, and routes traffic accordingly. Blocking the Ethereum RPC endpoints ( eth-mainnet.nodereal.io , go.getblock.io , eth.llamarpc.com ) from build containers is a more effective defense than blocking the exfiltration domain, since the RPC calls are what enable the attacker to cycle infrastructure. This is the first documented use of a blockchain smart contract as C2 infrastructure in any Shai-Hulud campaign wave.
The payload installed a token revocation watcher — a persistence mechanism that monitors for revoked credentials and fires an attacker-controlled local handler the moment a victim begins the standard incident-response procedure. Wiz's analysis found the watcher was selectively armed: the attacker's C2 server specifies which specific token to monitor by responding with a code value and the target token, enabling the attacker to target the highest-value credential on each compromised host individually, as detailed in Wiz's revocation-watcher documentation .
The payload also embeds an extortion string: IfYouBlockThisAPIKeyItWillCrashTheLiveProductionServersOfAllThirdPartyClients . This string carries no technical weight — the attacker cannot actually crash production servers by blocking a token — but it was specifically designed to make developers hesitate before rotating credentials. As Kodem's runbook states directly: the extortion string is psychological pressure. Revoke the token. But revoke it from a clean, isolated device, not from the potentially compromised host.
Security teams at Aikido, SafeDep, Socket, and Kodem issued an urgent warning based on this mechanism: do not begin incident response by revoking credentials from a potentially compromised host. The correct sequence is to isolate the host first, remove the persistence mechanism, then rotate from a clean device. This reversal of the standard incident-response playbook is the most immediately actionable thing a developer reading this article needs to know.
Perhaps the most alarming dimension of Wave Six — the one that matters most to every organization that has invested in supply-chain security controls — is that every standard integrity check passed cleanly.
Because the attacker pushed code through the maintainer's own legitimate GitHub Actions release workflow, [email protected] was published to npm with valid OIDC provenance and a SLSA attestation, as Snyk's tarball comparison confirmed . Kodem stated the structural failure plainly: "Provenance, SLSA, and OIDC trusted publishing all worked as designed and all signed malicious artifacts." As Wiz's analysis described, provenance proves where an artifact was built and that nothing tampered with it afterward — it cannot prove that the source code pushed into the pipeline before it ran was safe, or that legitimate credentials authorized its submission, per Wiz's provenance limitations analysis .
This is the "trusting trust" problem that computer scientist Ken Thompson identified in his 1984 Turing Award lecture, now operating at npm ecosystem scale. The attestation correctly proved the package was built by the real release pipeline from the real repository. It could not prove the code that entered that pipeline was not attacker-controlled. Two consecutive Shai-Hulud waves — Miasma in June and Wave Six in August — have now exploited trusted publishing as the propagation channel rather than defeating it, as covered in TechTimes' earlier Red Hat Miasma report . The control that the industry built to stop this attack has now become the mechanism the attack uses to spread.
Teams on npm 12 or newer have partial protection: the current npm major blocks unapproved preinstall lifecycle scripts by default. The IDE and agent configuration hook vectors remain active regardless of npm version.
Yes. If a developer opened the cloned keyv repository in VS Code or started a Claude Code session inside it, the .vscode/tasks.json folderOpen task or the .claude/settings.json SessionStart hook could trigger the loader without any package installation step. Both VS Code and Claude Code apply workspace trust controls before honoring these configurations automatically, but once a developer trusts a project, those controls may no longer apply, as noted in BreachNews' worm coverage . Organizations should review both installed npm packages and local repository clones on developer workstations — simply uninstalling a malicious dependency is not sufficient cleanup if repository-based execution paths are already present.
What elevated Wave Six beyond a typical compromised package was its autonomous self-replication. Socket and Aikido decoded machinery within the payload for modifying, versioning, and republishing npm packages using whatever publishing tokens the worm had just stolen.
Using a victim's npm token, the payload queried the registry to list every package that token can publish. It then fetched each tarball, injected the identical preinstall hook and payload files, recomputed integrity fields so the tarball still validates, bumped the patch version by one, and republished through npm's OIDC trusted publishing endpoint — using that trusted infrastructure as the propagation channel itself. Aikido observed 50 to 100 newly infected packages every few minutes during peak propagation. By 1:37 p.m. ET on August 4, the count had reached at least 434 packages across 1,381 versions, representing more than two billion combined monthly installs, per Aikido's live propagation tracking .
Vendor tallies diverged as the incident unfolded, which is normal during live worm propagation: Endor Labs verified 373 packages across 1,006 malicious versions; Cloudsmith tracked 2,236 versions; OX Security and Wiz placed the distinct package count at 400 to 440 or more. None of those figures represents a complete, independently verified list, and none measures how many developer machines or CI runners actually executed the payload, as Kodem acknowledged in their Wave Six runbook .
Multiple security firms placed the attack within the Shai-Hulud malware family, a lineage of self-propagating npm worms that researchers have tracked since at least September 2025. Kodem Security documented this as the sixth major wave, tracing a lineage through the original September 2025 npm campaign, Shai-Hulud 2.0, The Golden Path, the SAP package compromise, the Miasma variant against Red Hat's official @redhat-cloud-services namespace in June 2026, and Mini Shai-Hulud, per their full lineage documentation .
Wiz's analysis identifies the Wave Six payload as a descendant of the Mini Shai-Hulud malware family, sharing the identical hook filenames ( setup.mjs ), the pinned Bun 1.3.13 runtime, and the same credential-harvesting architecture that Kodem documented in an April 2026 compromise of PyPI's lightning package. Three elements distinguish Wave Six from all prior waves: IDE and agent hook persistence as a primary execution path rather than a variant behavior, the selective token revocation watcher with its extortion string, and npm OIDC trusted publishing used as the worm's propagation channel. The threat actor behind this specific wave and the method used to gain initial access to the keyv maintainer account remain unknown.
Security teams whose dependency lockfiles resolved any affected package version on or after August 4 should treat the environment as actively credential-exposed. The correct response sequence — drawn from guidance by Kodem, SafeDep, Socket, Aikido, and Snyk — is as follows.
Do not rotate credentials from the potentially compromised host first. The payload's token revocation watcher may trigger an attacker-controlled handler. Isolate the machine.
Remove persistence indicators before touching any credential. Hunt for gh-token-monitor.sh , systemd unit gh-token-monitor.service , LaunchAgent plist com.user.gh-token-monitor.plist , /tmp/bun-dl-* directories, and Math_Symbol.js or math_init.js on disk, per Kodem's IOC and runbook guidance . Also check for .claude/settings.json with a SessionStart hook and .vscode/tasks.json with a folderOpen task — in both the compromised npm packages and in any cloned repositories on the workstation.
Pin all affected packages to the last clean version using exact version strings in an overrides block, run npm install --ignore-scripts , clear the cache, and rebuild lockfiles from scratch. Verify by integrity hash.
From a clean, isolated device: rotate all credentials that the affected runner or workstation could have reached — npm tokens, GitHub tokens (all formats: ghp_ , gho_ , ghs_ ), AWS access keys and assumed roles, Google Cloud and Azure credentials, Kubernetes service account tokens, HashiCorp Vault tokens, Stripe and Slack keys, SSH keys, and anything matched by a broad secret-file scan of the affected machine.
Audit Git and GitHub activity: your organization for any repository created with the description "Shai-Hulud: Here We Go Again," and review for unauthorized publish events or patch-version bumps nobody initiated.
Teams on npm 12 or newer have partial protection: the current npm major blocks unapproved preinstall lifecycle scripts by default. The IDE and agent configuration hook vectors remain active regardless of npm version.
As of August 5, 2026, neither npm nor GitHub had issued a public statement on the incident. npm had begun rolling back latest tags on at least nine affected seed packages. No statement from the keyv maintainer had been located publicly. Indicators of compromise are maintained by Wiz Research at the Wiz Research IOC repository .
Wave Six introduced three capabilities that no prior wave shipped: executable payloads inside AI coding agent configuration files ( .claude/settings.json ) and IDE task files ( .vscode/tasks.json ) that fire without any npm install; a command-and-control layer that routes through an Ethereum smart contract, letting the attacker rotate infrastructure without modifying the payload; and a token revocation watcher that triggers attacker-controlled code when a defender attempts to rotate stolen credentials from a compromised host. Kodem Security's runbook documents this as the sixth major wave in the Shai-Hulud family and identifies these three features as the specific technical advances over prior waves, per Kodem's Wave Six analysis .
Cryptographic attestations verify that a package was built by a specific pipeline from a specific repository, and that the artifact was not tampered with after build. They cannot verify that the source code pushed into the pipeline before it ran was safe. Because the attacker compromised the maintainer's GitHub account and pushed malicious code directly to the repository, the legitimate GitHub Actions release workflow faithfully built and attested a malicious artifact. As Kodem put it, "Provenance, SLSA, and OIDC trusted publishing all worked as designed and all signed malicious artifacts." This is a structural limit in artifact-level integrity verification — the "trusting trust" problem identified by computer scientist Ken Thompson — not a failure of the attestation standard itself. Runtime behavioral monitoring (detecting a caching library spawning a second JavaScript runtime and reading cloud metadata) catches what static attestations cannot, as explained in Kodem's structural analysis .
Do not revoke credentials from the potentially compromised host first — the payload's token revocation watcher may fire an attacker-controlled handler when it detects a revocation attempt. The correct sequence is: (1) isolate the machine; (2) remove persistence artifacts ( gh-token-monitor.sh , com.user.gh-token-monitor.plist , Math_Symbol.js , and the .claude/settings.json and .vscode/tasks.json hooks); (3) pin affected packages to clean versions and rebuild the dependency tree with --ignore-scripts ; (4) then rotate all credentials — npm tokens, GitHub tokens, AWS keys, cloud credentials, Kubernetes configs, Vault tokens, SSH keys — from a separate, clean device. Treat the affected workstation or CI runner as fully credential-exposed regardless of lockfile results, because the preinstall hook executes before any install completes, per Kodem's first-hour runbook .
The Wave Six payload does not embed a C2 domain in its code. Instead, it queries a StringListStore smart contract deployed on the Ethereum mainnet at address 0xE1f2395ee43e45A1556EC6438a88c31B83493103 , using a standard eth_call to read the current list of C2 domains from the blockchain. The attacker can update that list at any time simply by submitting a transaction to the contract — no payload modification, no new deployment required. Blocking the C2 domain npm-cache[.]com is therefore insufficient: the attacker updates the contract, and all infected nodes receive the new address on their check. The more durable defense is blocking outbound access to Ethereum RPC endpoints ( eth-mainnet.nodereal.io , go.getblock.io , eth.llamarpc.com ) from build containers and developer workstations that have no legitimate need to query blockchain infrastructure, as Wiz Research explains in their Ethereum C2 breakdown .
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
