














The exact account takeover mechanism the attacker leveraged is unknown at this time. Once inside, the attacker pushed two malicious files, setup.mjs and Math_Symbol.js, directly to the main branches of the affected repositories, and modified package.json to add a preinstall hook. The figure below shows the package.json modification that triggers setup.mjs.

Figure 1: Shows the package.json modification that triggers setup.mjs in the ChainDrop attack flow.
Because the attacker operated as the legitimate maintainer, the project's existing GitHub Actions release workflow kicked in automatically, built the poisoned package, and published it to npm with valid OIDC trusted-publisher provenance and a valid SLSA Build Level 3 attestation.
The setup.mjs file runs automatically when any developer or CI system executes npm install. The file does the following:
The attacker uses Bun deliberately. By running the payload outside of the standard node process, the attacker bypasses security tools and endpoint detection and response (EDRs) that specifically monitor Node.js child-process behavior. The following figure shows the portion of setup.mjs that specifies the next-stage filename and references bun.exe.

Figure 2: Shows setup.mjs trying to load Math_Symbol.js using bun.exe.
The Math_Symbol.js file is a heavily obfuscated file executed by Bun, as shown in the figure below.

Figure 3: Obfuscated Math_Symbol.js file.
The Math_Symbol.js file performs the following:
Credential harvesting
The payload performs a broad sweep of the infected environment, targeting:
npm tokens from ~/.npmrc, environment variables (NPM_TOKEN), and CI runner contexts.GITHUB_TOKEN, and OIDC tokens from runner memory.VAULT_TOKEN and related environment variables.Worm propagation
If the payload finds a valid npm token with publishing rights, it will:
Query the npm registry to enumerate all packages that are owned or writable by that token.
For each package, the payload fetches the current tarball.
Injects setup.mjs and Math_Symbol.js into the package and adds the preinstall hook to package.json.
Bumps up the patch version (e.g., '1.2.3' → '1.2.4').
Publishes the new poisoned version to the npm registry using the stolen token.
This is what caused the spread from the initial compromised packages to completely unrelated organizations. Developers at those organizations had installed a poisoned version in their CI runners, where the malware stole their publishing tokens and then used them to republish additional compromised packages under their own accounts.
Data exfiltration
Stolen credentials are serialized to JSON, compressed, and encrypted using AES-256-GCM with a randomly generated key. That key is then wrapped with an RSA-4096 public key embedded in the payload. The encrypted data is exfiltrated via two channels:
eth_call to retrieve active C2 domains. The confirmed fallback domain was npm-cache[.]com. Persistence, AI agents, and IDE hooks
In a notable evolution from earlier Shai-Hulud waves, ChainDrop plants execution hooks that target modern AI-assisted developer tooling:
These hooks allow the malware to re-execute when a developer opens a project folder in an IDE or starts an AI agent session with no npm install required. This persistence can also survive package cleanup.
Token revocation trap
The worm installs a background process (identified as gh-token-monitor in some variants) that polls the GitHub API every 60 seconds using the stolen token. If the token returns a 4xx error, indicating the victim has revoked it, the worm triggers a secondary destructive payload. Depending on the variant, this can include remote code execution or deletion of the user's home directory.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。