TL;DR
- Microsoft's writeup (Typosquatted npm packages used to steal cloud CI/CD secrets) covers 14 packages published today by one alias (
vpmdhaj) in a four-hour window, typosquatting OpenSearch/Elasticsearch tooling. All ran apreinstallharvester — norequire()from your code needed, justnpm install. - The detail worth your attention: there were two generations. Gen-1 beaconed to
aab.sportsontheweb[.]netwith anX-Supply: 1header and pulled a ~195 KB Bun-compiled payload. Gen-2 bundled the harvester into the tarball and stopped beaconing — no outbound C2 to catch on egress. - Targets: AWS creds via IMDSv2 (
169.254.169.254) and Secrets Manager across 16+ regions,VAULT_TOKEN, npm publish tokens via/-/whoamiand/-/npm/v1/tokens, and GitHub Actions runner context. Packages are taken down. If a CI job ran an install of anything OpenSearch-named today, rotate the creds that job could see.
The novelty isn't the harvester, it's losing the network signature
Credential-stealing preinstall packages are the genre of the month — we wrote up the Sicoob NuGet SDK yesterday, which hid its exfil in a constructor instead of a hook. The vpmdhaj cluster's payload is standard issue: a Bun-compiled binary that scrapes the cloud-CI credential surface. What's worth tracing is how the two generations differ on detection surface, because they invert the usual assumption that supply-chain malware is loud on the wire.
Gen-1 is the shape most network detections are tuned for:
preinstall.jsruns onnpm install.- It beacons to
aab.sportsontheweb[.]net(endpoint/x.php), tagged with headerX-Supply: 1. - The server returns a gzipped
payload.bin(~195 KB), Bun-compiled, run detached (__DAEMONIZED=1).
A proxy log or egress allowlist catches step 2. The C2 domain is an IOC you can block and hunt retroactively.
Gen-2 deletes that signal:
setup.mjsdownloads the legitimate Bun runtime v1.3.13 straight fromgithub.com/oven-sh/bun/releases— a normal-looking fetch from a real vendor, not a flagged C2.- The harvester (
opensearch_init.js/ai_init.js) is pre-bundled in the tarball, so there's no install-time C2 round-trip to intercept. - Only the exfil of stolen creds leaves the box — and that can ride whatever channel the harvester picks, after the secrets are already in hand.
The defender lesson: blocking the Gen-1 C2 domain does nothing for Gen-2. Fetching a real toolchain binary (Bun) is indistinguishable from a legitimate postinstall that, well, fetches a toolchain. The catchable moment moves earlier — to the install event itself — and later — to the credential being used somewhere it shouldn't.
What to actually do
The reader action is the same one that keeps coming up, with one addition this round:
- Rotate first, hunt second. If a CI job installed an OpenSearch/Elasticsearch-named package today, assume the secrets that job's environment exposed are gone: AWS instance-role creds,
VAULT_TOKEN, npm publish tokens, GitHub Actions secrets. Rotate before you finish reading the IOCs. - Block the install, not just the C2. The Gen-1 IOCs (
aab.sportsontheweb[.]net,X-Supply: 1, hashes in Microsoft's post) are worth blocking, but Gen-2 proves egress IOCs are a backstop, not a control. The control is a minimum release age on installs — refuse to pull a version published in the last N hours — which would have caught every one of these in their four-hour publish window. In pnpm it's theminimumReleaseAgesetting inpnpm-workspace.yaml(e.g.minimumReleaseAge: 1440for a one-day hold; it covers transitive deps too). - Scope IMDS access. A harvester hitting
169.254.169.254from a CI runner is the loudest tell you have left in Gen-2. IMDSv2 hop-limit and metadata-access denial for build containers turns "scrape the instance role" into a non-event.
The thing to internalize: a 195 KB binary that pulls Bun and runs locally has roughly the same network footprint as a build that legitimately pulls Bun and runs locally. Detection budgets aimed at C2 domains are spending against the generation the attacker already abandoned.
Sources
- Microsoft Security Blog, Typosquatted npm packages used to steal cloud CI/CD secrets (2026-05-28) — https://www.microsoft.com/en-us/security/blog/2026/05/28/typosquatted-npm-packages-used-steal-cloud-ci-cd-secrets/
- pnpm
minimumReleaseAgesetting — https://pnpm.io/settings#minimumreleaseage - AWS IMDSv2 configuration — https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html