Skip to content

npm supply-chain campaign: 14 typosquats target AWS, Vault, npm tokens

Microsoft says a single maintainer 'vpmdhaj' pushed 14 typosquatted npm packages on May 28 that exfiltrate AWS, ECS, HashiCorp Vault and npm tokens via a Bun-runtime payload.

Published 3 min read

Microsoft Threat Intelligence published on May 28, 2026 a writeup on an active npm supply-chain campaign: a single newly-created maintainer alias, vpmdhaj (a39155771@gmail.com), pushed 14 typosquatted packages in a four-hour window that harvest cloud and CI/CD secrets from any environment running npm install. The packages typosquat or impersonate OpenSearch, ElasticSearch, and environment-config libraries; several spoof the upstream OpenSearch GitHub URL in their package.json to bait dependency vetting.

Primary writeup: Typosquatted npm packages used to steal cloud and CI/CD secrets — Microsoft Threat Intelligence. The Register has confirmation reporting.

The 14 packages

Names and versions are reproduced verbatim from the Microsoft advisory.

Scoped:

  • @vpmdhaj/elastic-helper (1.0.7269)
  • @vpmdhaj/devops-tools (1.0.7267)
  • @vpmdhaj/opensearch-setup (1.0.7267)
  • @vpmdhaj/search-setup (1.0.7268)

Unscoped:

  • opensearch-security-scanner (1.0.10)
  • opensearch-setup (1.0.9103)
  • opensearch-setup-tool (1.0.9108)
  • opensearch-config-utility (1.0.9106)
  • search-engine-setup (1.0.9108)
  • search-cluster-setup (1.0.9104)
  • elastic-opensearch-helper (1.0.9108)
  • vpmdhaj-opensearch-setup (1.0.9102)
  • env-config-manager (2.1.9201)
  • app-config-utility (1.0.9300)

How it runs

Execution is triggered by a preinstall lifecycle hook — install-time, no developer code path required. Microsoft documents two stager generations:

  • Gen-1: node → preinstall.js → HTTP C2 → payload.bin (detached).
  • Gen-2: node → setup.mjs → downloads the legitimate Bun runtime → runs a bundled stage-2.

Stage two is a ~195 KB Bun-compiled credential harvester (alternate filenames: opensearch_init.js, ai_init.js, payload.bin). It targets:

  • AWS — IMDSv2 at 169.254.169.254, ECS task-role metadata at 169.254.170.2, Secrets Manager enumeration across 16+ regions, STS GetCallerIdentity and AssumeRole.
  • HashiCorp VaultVAULT_TOKEN and VAULT_AUTH_TOKEN environment variables.
  • npm — registry tokens via /-/whoami and /-/npm/v1/tokens, explicitly to enable follow-on supply-chain pivots.
  • GitHub ActionsGITHUB_REPOSITORY and RUNNER_OS context.

Indicators of compromise

Verbatim from the Microsoft Threat Intelligence advisory:

Domain:   aab.sportsontheweb[.]net
C2 URL:   http://aab.sportsontheweb[.]net/x.php   (port 80)
Header:   X-Supply: 1

SHA-256 (preinstall.js): 638788AFC4F1B5860A328312CAF5895ABD5F5632D28A4F2A85B09076E270D15D
SHA-256 (setup.mjs):     77D92EFE7AF3547F71FD41D4A884872D66B1BE9499EAA637E91EAC866911694D
SHA-256 (payload.gz):    BFA149694EC6411C23936311A999163ADE54D6F38E2F4B0E3CFB8CB67BD7CFAA

Action checklist

  1. Grep your lockfiles and CI configs for any of the 14 names above. Direct dependencies are the obvious case; transitive pulls in someone else's dependency graph are the failure mode you actually need to find.
  2. Rotate cloud and CI secrets touched by any install host that ran an affected lockfile after May 28, 2026. The stager runs as part of npm install, so the blast radius is every CI runner, developer laptop, and build container that resolved a vulnerable tree. Rotate AWS access keys, refresh ECS task roles, revoke Vault tokens, regenerate npm publish tokens, and review GitHub Actions OIDC trust where the runner could have leaked context.
  3. Hunt the network signature. Outbound to aab.sportsontheweb[.]net or any HTTP request carrying the X-Supply: 1 header is the cheapest detection. EDR/XDR rules should also flag node processes issuing HTTP fetches during install lifecycle hooks.
  4. Audit the Bun-runtime path. Gen-2 pulls the legitimate Bun binary and uses it as a living-off-the-land loader. If your control set assumes Bun is a developer-only tool that would never run on a build agent, fix that assumption — add the Bun installer URL to your allowlist review.
  5. Default builds to npm install --ignore-scripts in CI where it is feasible, and add explicit exceptions only for packages that genuinely need lifecycle scripts. Lifecycle hooks are the install-time foothold; if your pipeline doesn't need them, close the door.

Context

This is the second cross-language registry campaign we have covered this month where install-time scripts ship a credential stealer the moment a build runs: the Laravel-Lang Composer compromise on May 22–23 used the same shape on the Composer side. Across both: a freshly-created maintainer identity, a brief publication window, and a payload that executes before any human reads a README. Detection has to live at the registry side, not in the dependency tree of any single project.

The Bun trick is the new wrinkle. Bringing your own LotL binary breaks signature-based detection on node and on PowerShell scripts, while keeping the network footprint of "a build agent fetching a legitimate developer tool." Expect more campaigns to copy the pattern.

Related stories