Socket is tracking an active supply chain compromise in the keyv and cacheable npm ecosystems, where trojanized packages used a malicious preinstall hook to download Bun, steal cloud and CI credentials, and republish infected packages through stolen npm tokens. The campaign affected tens of millions of weekly downloads and also planted persistence in developer and AI coding environments via .claude and .vscode hooks. #keyv #cacheable #Jaredwray #Bun #npm #GitHubActions #HashiCorpVault
Keypoints
- At least ten npm packages in the keyv and cacheable ecosystems were published with a malicious preinstall hook on August 4, 2026.
- The compromised maintainer account âJaredwrayâ was used to publish across multiple package families, including packages outside the original namespaces.
- The malicious installer downloaded a standalone Bun runtime and executed a second-stage payload hidden in setup.mjs and Math_Symbol.js.
- The payload harvested cloud, CI, GitHub, npm, Vault, and Kubernetes credentials, then used stolen tokens to self-propagate by republishing trojanized npm packages.
- Stolen data was exfiltrated to threat actor GitHub repositories and DNS-resolved destinations, while autostart hooks were planted in .claude and .vscode.
- A host-level dead-manâs switch was installed to watch for token revocation and execute a remote-supplied handler when the stolen GitHub token stopped working.
- Socket detected [email protected] quickly after publication, but new malicious packages continued appearing in real time.
MITRE Techniques
- [T1195.002] Compromise Software Supply Chain â The threat actor altered npm packages in the release process to distribute malicious code (âpublished with a malicious preinstall hookâ and ârepublishes trojanized versions of other packagesâ).
- [T1546.016] Installer Packages â The malware executed during installation through npm lifecycle scripts (âpreinstallâ: ânode setup.mjsâ and âdelivered entirely through the npm lifecycleâ).
- [T1059.001] Command and Scripting Interpreter: JavaScript â The payload used Node.js and Bun scripts to run both stages (âsetup.mjs is a lightly obfuscated Node scriptâ and âexecFileSync(bunBinary, [payloadPath])â).
- [T1105] Ingress Tool Transfer â The loader downloaded a standalone Bun runtime from GitHub to execute the second stage (âdownloads a platform-matched standalone Bun runtimeâ).
- [T1552] Unsecured Credentials â The payload searched for and collected cloud, CI, and developer secrets (âharvests cloud and CI credentialsâ, âAWS/GCP/Azure keysâ, âHashiCorp Vault tokensâ, âKubernetes service account tokensâ, ânpm tokensâ).
- [T1530] Data from Cloud Storage â The collector queried cloud instance metadata and credential sources from cloud environments (âqueries the AWS instance metadata serviceâ and reads âAWS credential chains and Secrets Managerâ).
- [T1213] Data from Information Repositories â It pulled secrets and tokens from GitHub and repository-related sources (âenumerates GitHub Actions organization and repository secret metadataâ and commits stolen findings to GitHub repositories).
- [T1027] Obfuscated Files or Information â Strings in the second stage were protected with polymorphic basE91 encoding (âStrings are protected with polymorphic basE91 encodingâ).
- [T1071.001] Application Layer Protocol: Web Protocols â The malware used HTTPS, GitHub APIs, and npm registry endpoints for command, credential exchange, and publishing (âdownloads ⌠over HTTPSâ, âPOST /user/reposâ, âregistry.npmjs.org/-/npm/v1/oidc/token/exchange/package/â).
- [T1567.002] Exfiltration to Cloud Storage â Stolen data was sent to threat actor GitHub repositories (âcommits stolen findings using the GraphQL createCommitOnBranch mutationâ).
- [T1102.001] Web Service: Dead Drop Resolver â The DomainSender resolved destinations via DNS before sending data (âresolves destinations via DNS and health-checks them before sending encrypted dataâ).
- [T1547.001] Registry Run Keys / Startup Folder â Persistence was added through autostart hooks in repository and system startup locations (âplants autostart hooks in .claude and .vscodeâ and persists as a LaunchAgent or systemd user service).
- [T1490] Inhibit System Recovery â The dead-manâs switch triggered destructive cleanup on token revocation, removing its own state and exiting (âwhen the token stops working ⌠it evaluates a remote-supplied handler string, then deletes its state and exitsâ).
Indicators of Compromise
- [SHA-256] Malicious loader and payload files â 54dc7ea54a1317cca0e890a2770630cf7fa6c97813e0cb9d2caa93012b350668, 9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc
- [SHA-256] Repository loader variant â fd3ca4007b225fdf8de7af4345a19179d5efa8c4bb9205f88cda806e5684b1eb, and one other file hash mentioned in the article
- [SHA-512 tarball] Malicious npm package artifact â keyv-6.0.0.tgz / 37f9f847e9c3e520b47d83a9029e199dbc30c6a195a1d80467d0fb1a6fd5068728ad4d1a422995ca578359263afdac5d3b4fed7a6b9befad27de19cca6966952
- [File names] Installer and payload files â setup.mjs, Math_Symbol.js, and math_init.js
- [Network / IP] Cloud metadata service addresses used for credential theft â 169[.]254[.]169[.]254, 169[.]254[.]170[.]2
- [Network / Domain / URL] Bun download and npm/GitHub endpoints â github[.]com/oven-sh/bun/releases/download/bun-v1.3.13/, registry[.]npmjs[.]org/-/whoami, registry[.]npmjs[.]org/-/npm/v1/oidc/token/exchange/package/
- [Package names] Affected npm packages â [email protected], @cacheable/[email protected], [email protected], and other listed cacheable/keyv versions