Feed
CriticalPublished 4 Sept 202610 packages · 24 versions

GitHub Advisory malware sweep - 2026-09-04 batch (10-package npm-only day: `@bx-ui-framework/*` + `grivy-packages.com` remote-tarball hijack clusters + `@yuva2210/okx-poc-rce-impact` + `@avigilon/node-webrtc` dep-confusion recon + `wallet-watcher` BIP-39/ETH-key AES-256-GCM stealer + `mcp-consultasdeveiculos-client` CLI-token OOB exfil + `vitest-cli-dev` remote-`new Function()` dropper)

Summary

10-package npm-only sweep. Two remote-tarball hijack clusters (@bx-ui-framework/* via artifactorymanager.com/remoteknight.com; @grab-food/order-sdk-web+lil-swisgom-hlepers via grivy-packages.com), wallet-watcher BIP-39/ETH-key AES-256-GCM stealer, dep-confusion recon (OKX + Avigilon), and vitest-cli-dev remote-new Function() dropper.

dependency-confusioncredential-theftinfostealercrypto-wallet-draintyposquatobfuscationci-cd-compromise
Detected by
GitHub Advisory Database · OpenSSF malicious-packages · OpenSSF Package Analysis · Amazon Inspector
Also known as
2026-09-04 GHSA sweep · bx-ui-framework artifactorymanager remote-tarball hijack · grivy-packages.com remote-tarball hijack · wallet-watcher BIP-39 ETH stealer · vitest-cli-dev remote new Function dropper
Ecosystems
npm
Packages tracked
10

What happened

The 24-hour window ending 2026-09-04 published 10 new npm malware advisories and zero new PyPI ones - all PyPI activity for the day rolled up under the already-catalogued Sept 3 2026-09-telemetry-helper campaign. The npm day breaks into six clusters, all published by the GitHub Advisory Database on Sept 4 and sourced through OpenSSF malicious-packages + Amazon Inspector + OpenSSF Package Analysis feeds.

Two of the six clusters are the same TTP class - package.json declaring a runtime dependency as a bare HTTPS URL to an attacker-controlled tarball host. This is a lower-effort variant of the classic install-script credential steal because the visible npm tarball is empty; the malicious code is fetched from the operator's host at install time and can be silently rotated between installs. Static scanners auditing the npm registry copy see nothing.

Cluster A - @bx-ui-framework/* bare-URL remote-tarball dep-confusion (3 packages)

| Package | Versions | GHSA | Tarball host | |---|---|---|---| | @bx-ui-framework/microfrontend | 15.0.0 | GHSA-v4h4-57j3-83rp | repo.artifactorymanager.com | | @bx-ui-framework/authentication | 1.2.0, 15.0.0 | GHSA-9q5c-jq8f-775p | repo.artifactorymanager.com | | @bx-ui-framework/common | 1.2.0, 15.0.0 | GHSA-m2pp-gxpx-9chq | repo.remoteknight.com |

Each package.json declares its dependency as a bare https://<attacker-host>/<path> URL - no version, no integrity hash, no signature. On npm install, npm fetches whatever bytes the operator serves and executes any lifecycle scripts they contain. The @bx-ui-framework scope has no verified enterprise publisher on npm; the operator picked a plausible dep-confusion scope name and used two different attacker hosts across three packages (a light attempt to defeat host-based domain blocklists).

Why the pattern is dangerous: because the tarball is fetched fresh on every install, a poisoned lockfile does not preserve the payload for forensic replay. A rebuild against a mirror that no longer serves the URL yields a "clean" install even though a compromised host has already executed the operator's code once. Assume worst-case for any host that install-scripted these packages in the exposure window.

Cluster B - grivy-packages.com remote-tarball hijack (2 packages)

| Package | Versions | GHSA | Tarball host | Target scope | |---|---|---|---|---| | @grab-food/order-sdk-web | 49.9.9 | GHSA-84w3-v779-4w52 | registry.grivy-packages.com | Grab (SEA super-app) | | lil-swisgom-hlepers | 49.9.9 | GHSA-wqg5-6mgg-v9gq | registry.grivy-packages.com | typo of swisgom-helpers |

Same attacker host, same 49.9.9 pinned tag on both packages - one operator. index.js is an empty stub; the entire behaviour lives in the -core dependency tarball fetched from grivy-packages.com. @grab-food/order-sdk-web targets Grab internal dep-confusion; lil-swisgom-hlepers mistypes the legitimate name to catch fat-fingering developers.

Cluster C - Dep-confusion reconnaissance drops (2 packages)

| Package | Versions | GHSA | Target scope | Exfil channel | |---|---|---|---|---| | @yuva2210/okx-poc-rce-impact | 2.0.0 | GHSA-rvf4-r4vv-m3v8 | OKX (crypto exchange) internal | /tmp/okx-poc-rce-proof.json (local marker, no network) | | @avigilon/node-webrtc | 2.1.4, 2.1.5 | GHSA-qm5q-ggwg-5m4q | Avigilon/Motorola video-surveillance internal | *.burp.attack.live OAST callback |

Both are recon PoCs, not weaponised implants. The OKX PoC does not phone home - it writes a proof marker to /tmp for the attacker to correlate later (perhaps via a follow-up drop that reads the marker, or via manual review of accessible dev hosts). The Avigilon package uses burp.attack.live - a Burp Collaborator-style out-of-band callback service - to detect installs without a distinctive C2 host.

These are not the attack. They are the fingerprinter that tells the operator which internal namespaces resolve to public npm on their target's network. If either package fired on your infrastructure, the follow-up weaponised drop is coming in the next 2-14 days.

Cluster D - wallet-watcher BIP-39/ETH-key AES-256-GCM stealer (1 package)

| Package | Versions | GHSA | |---|---|---| | wallet-watcher | <=1.0.2 | GHSA-fvcm-93j7-7f35 |

Attack chain:

  1. npm install wallet-watcher → postinstall src/scan.cjs runs
  2. Walks the project tree starting three directory levels above node_modules - this is deliberate: it escapes past nested node_modules/wallet-watcher/node_modules/... layouts and touches the real workspace root
  3. Greps .env, .js, .ts, .json, .py, .yml, and keystore files for: BIP-39 wallet mnemonics, 0x-prefixed 64-hex Ethereum private keys, and assignments matching secret/api_key/mnemonic
  4. AES-256-GCM-encrypts findings with a hardcoded key (traffic decryptable once the key is extracted from the tarball)
  5. Tags payload with host+username hash and POSTs to the operator
  6. Also runs at runtime: the exported getBalances() function re-invokes the scanner against the caller's CWD on every call - so --ignore-scripts does not defeat it, only removing the package does

The three-levels-up scan and the runtime-callback fallback are the two features that make this one worse than the average preinstall stealer. Any developer laptop that installed AND ever imported wallet-watcher has surrendered every crypto wallet whose seed or private key sat in the workspace tree.

Cluster E - mcp-consultasdeveiculos-client CLI-token OOB exfil (1 package)

| Package | Versions | GHSA | Exfil | |---|---|---|---| | mcp-consultasdeveiculos-client | 0.0.2, 0.1.0, 0.1.1 | GHSA-fp7g-2255-xxrp | *.oob.lyomeri.com/npm-exec |

The package README falsely claims "contains NO code and NO install scripts". In fact, bin/main runs on npx -y mcp-consultasdeveiculos-client --token <value> and exfils the full argv (including the --token value) alongside hostname, username, OS platform/arch, Node version, and CWD to *.oob.lyomeri.com. The package name was picked to match an unclaimed identifier referenced in external MCP-tooling documentation - anybody following the doc's npx snippet handed the operator whatever token they were told to include.

Generalisable lesson: npx runs untrusted code by design. Passing a secret on the command line for any npx-invoked tool means the secret is exfiltrated the first time the name resolves to a hostile publisher.

Cluster F - vitest-cli-dev remote-new Function() dropper (1 package)

| Package | Versions | GHSA | |---|---|---| | vitest-cli-dev | <=10.0.7 | GHSA-f6wj-75hx-p44c |

Typosquats the legitimate vitest CLI. Postinstall spawns a detached child process that fetches JSON from two remote JSON-storage endpoints and executes the response via new Function(). Ships a disguised copy of nodemailer in the tree to look legitimate. Payload is mutable and served remotely - a snapshot of the npm tarball's behaviour at time-of-audit is a lower bound.

Registry state

All 10 packages listed above were flagged as malware on the npm registry on 2026-09-04 and have been added to the npm quarantine list. Private mirrors (Verdaccio, Artifactory, Nexus) that cached tarballs before the takedown will keep serving the malicious versions. The dependency URLs pointing at artifactorymanager.com, remoteknight.com, and grivy-packages.com will continue to resolve if you install a poisoned lockfile that already references them, so blocking those hostnames at the network edge is a durable mitigation independent of registry-side quarantine.

Discovery credits

GitHub Advisory Database, OpenSSF malicious-packages, OpenSSF Package Analysis, Amazon Inspector.

Affected packages (10)

These are usually pulled in as transitive dependencies rather than installed directly. Check your whole tree at once - it runs in your browser and nothing is uploaded.

Impact

  • *Cluster A - `@bx-ui-framework/ bare-URL remote-tarball dep-confusion (3 packages, 5 versions)**: @bx-ui-framework/microfrontend@15.0.0 (GHSA-v4h4-57j3-83rp) sources its dependency from https://repo.artifactorymanager.com/bx-ui-framework/microfrontend; @bx-ui-framework/authentication@1.2.0+15.0.0 (GHSA-9q5c-jq8f-775p) from https://repo.artifactorymanager.com/bx-ui-framework/authentication; @bx-ui-framework/common@1.2.0+15.0.0 (GHSA-m2pp-gxpx-9chq) from https://repo.remoteknight.com/bx-ui-framework/common. All three package.json files declare a runtime dependency as a bare HTTPS URL (no version pin, no integrity hash, no signature) rather than a registry version - npm install fetches whatever bytes the attacker-controlled host returns and executes any lifecycle scripts they contain, on every install. **The remote payload is mutable** - the operator can change the tarball at any time without republishing the visible npm package. artifactorymanager.com and remoteknight.com are unrelated to any legitimate @bx-ui-framework` publisher
  • Cluster B - grivy-packages.com remote-tarball hijack (2 packages, 2 versions): @grab-food/order-sdk-web@49.9.9 (GHSA-84w3-v779-4w52) declares a pinned dependency grab-food-order-sdk-web-core@49.9.9 from https://registry.grivy-packages.com/; lil-swisgom-hlepers@49.9.9 (GHSA-wqg5-6mgg-v9gq) declares lil-swisgom-hlepers-core from the same host. Same 49.9.9 version tag, same attacker host - one operator. index.js is an empty stub; the entire malicious behaviour ships in the remotely-fetched dependency tarball, so the visible npm package looks inert to static scanners. @grab-food/order-sdk-web targets Grab (SEA super-app) internal dep-confusion; lil-swisgom-hlepers is a typo of a legitimate swisgom-helpers-shaped utility
  • Cluster C - dep-confusion reconnaissance drops (2 packages, 3 versions): @yuva2210/okx-poc-rce-impact@2.0.0 (GHSA-rvf4-r4vv-m3v8) is a preinstall PoC targeting OKX internal namespace; runs whoami, hostname, pwd, id via child_process.execSync and writes results to /tmp/okx-poc-rce-proof.json - proves internal-namespace resolution to the attacker without triggering egress alerts. @avigilon/node-webrtc@2.1.4+2.1.5 (GHSA-qm5q-ggwg-5m4q) targets Avigilon (Motorola video-surveillance) internal namespace; preinstall exfils hostname, username, home directory, DNS server config, install path, and package manifest to mj9ouelpgm0d26s3wp0syow03r9ix8lx.burp.attack.live (burp.attack.live is an out-of-band callback domain popular for Burp Collaborator-style OAST fingerprinting). Both are low-yield reconnaissance; expect a weaponised follow-up drop against confirmed-vulnerable installs within 2-14 days
  • Cluster D - wallet-watcher BIP-39/ETH-key AES-256-GCM stealer (1 package, 3 versions): wallet-watcher@<=1.0.2 (GHSA-fvcm-93j7-7f35) runs a postinstall src/scan.cjs that walks the project tree starting three directory levels above node_modules (so it escapes past a nested-node_modules install and touches the real workspace root) and greps .env, .js, .ts, .json, .py, .yml, and keystore files for BIP-39 mnemonics, 0x-prefixed 64-hex Ethereum private keys, and assignments matching secret/api_key/mnemonic. Finds are AES-256-GCM-encrypted with a hardcoded author-controlled key (so packet captures containing the encrypted blob decrypt trivially once the key is extracted), tagged with host+username hash, and POSTed to the operator. Also runs at runtime: the exported getBalances() re-invokes the scanner against the caller's CWD every call, defeating npm install --ignore-scripts. Any developer machine or CI runner that installed OR imported wallet-watcher since publish must rotate every wallet mnemonic, ETH private key, and API secret discoverable in the workspace
  • Cluster E - mcp-consultasdeveiculos-client CLI-token OOB exfil (1 package, 3 versions): mcp-consultasdeveiculos-client@0.0.2+0.1.0+0.1.1 (GHSA-fp7g-2255-xxrp). Package README falsely advertises "contains NO code and NO install scripts" but bin/main runs on npx -y mcp-consultasdeveiculos-client --token <value> and exfils hostname, username, OS platform+arch, Node version, CWD, and all CLI arguments including the --token value to dacgtekq6f43u7lptufg3hi1ytthx3skj.oob.lyomeri.com/npm-exec. The package name deliberately matches an unclaimed identifier referenced in external MCP-tooling documentation - the attacker registered it to intercept developers copy-pasting the setup command. Any developer who ran the documented npx invocation surrendered whatever token they passed on the command line
  • Cluster F - vitest-cli-dev remote-new Function() dropper (1 package, 8 versions): vitest-cli-dev@<=10.0.7 (GHSA-f6wj-75hx-p44c) typosquats the legitimate vitest CLI. Postinstall spawns a detached child process (survives npm-install termination) that fetches JSON payloads from two remote JSON-storage endpoints and passes the response through new Function() for arbitrary JavaScript execution. Mutable remote payloads = the operator changes malicious instructions without republishing, so a scan of the tarball snapshot is a lower bound. Ships a disguised copy of nodemailer in the tree to appear legitimate to a superficial audit

What to do

  1. 1Grep every package-lock.json, yarn.lock, pnpm-lock.yaml, and any bespoke npm registry mirror for the 10 package names below. Uninstall and rebuild the lockfile against a clean cache on any hit
  2. 2*For Clusters A + B (`@bx-ui-framework/ + @grab-food/order-sdk-web + lil-swisgom-hlepers remote-tarball hijack)**: block outbound connections from build/CI hosts to artifactorymanager.com, remoteknight.com, and grivy-packages.com regardless of whether you know you installed a listed package - these are attacker-controlled tarball origins that pin no version and can silently repopulate old installs. If your organisation maintains internal packages under @bx-ui-framework, @grab, @grab-food, or similar scopes, pin every scope to your private registry in .npmrc (@bx-ui-framework:registry=https://your-private-mirror/) and audit for any dependencies: entry in your own package.json files that is a bare HTTPS URL - that pattern is the entire attack vector. **The malicious tarball is served fresh on every install**, so a --offline` reinstall against a poisoned lockfile does not save you; regenerate the lockfile from scratch against a registry-pinned mirror
  3. 3For Cluster C (dep-confusion recon @yuva2210/okx-poc-rce-impact, @avigilon/node-webrtc): OKX and Avigilon/Motorola engineers should audit their private-registry precedence rules NOW - if either package resolved on any developer or CI host, the operator now has proof your internal namespace resolves to public npm and a weaponised follow-up drop is coming. Add explicit .npmrc scope pinning (@avigilon:registry=, @yuva2210:registry=). Block outbound to *.burp.attack.live and *.oastify.com from build hosts - both are OAST-callback services with no legitimate build-time use. Search for /tmp/okx-poc-rce-proof.json on any host that ran npm install in the exposure window - its presence confirms the preinstall reconnaissance ran
  4. 4For Cluster D (wallet-watcher BIP-39/ETH-key stealer): any workstation, CI runner, or contributor laptop that installed OR imported wallet-watcher@<=1.0.2 must be treated as having exfiltrated every wallet mnemonic, Ethereum private key, and file matching secret/api_key/mnemonic grep patterns anywhere in the workspace root (three levels up from node_modules). Rotate every crypto wallet whose seed phrase or private key was written to disk on that host. Rotate every API secret in the workspace. Because the scanner ALSO runs on getBalances() call, --ignore-scripts does not stop it. If your DLP allows tagging traffic destinations, flag outbound POSTs from Node processes carrying AES-GCM blobs of 200-2000 bytes to non-major-cloud endpoints during the exposure window
  5. 5For Cluster E (mcp-consultasdeveiculos-client): any developer or CI job that ran npx -y mcp-consultasdeveiculos-client --token <value> must treat the exfiltrated token as compromised - rotate it. Block outbound to *.oob.lyomeri.com. The lesson here is broader: npx runs untrusted code by design; requiring --token on the command line for any npx-invoked tool means the token is exfiltrated the first time anyone typosquats or resolves-then-hijacks the name. Prefer environment variables or config files for any secret consumed by an npx command
  6. 6For Cluster F (vitest-cli-dev): uninstall from lockfile and rebuild. Because the payload lives on a mutable remote JSON endpoint and executes via new Function(), static analysis of the tarball is a lower bound - assume worst case. Rotate credentials accessible to any host that installed the package
  7. 7For every npm install in CI, prefer --ignore-scripts - this blocks Clusters A/B/C/E/F preinstall+postinstall vectors. Cluster D still fires on require()+getBalances() call - the only defence is not resolving wallet-watcher at all
  8. 8Verify none of the enumerated packages still resolves via your private mirror - internal caches (Nexus / Artifactory / Verdaccio / Sonatype / devpi) routinely keep serving yanked tarballs after the public takedown

References

multi-2026-09-04-ghsa-malware-sweep