GitHub Advisory malware sweep — 25 npm packages (Epic Games / Unreal Engine internal-scope dependency-confusion cluster, LuminaryCloud, Reddit Voyager, nodemon family) taken down 2026-07-09 / 2026-07-10
On 2026-07-09 and 2026-07-10 GitHub's Advisory Database retired 25 CWE-506 Embedded Malicious Code npm advisories. The main story is a coordinated dependency-confusion burst against internal enterprise namespaces — Epic Games / Unreal Engine build tooling (robomerge, unreal-horde-dashboard, ue-jenkins-buildkite, ue-automation-scripts, epic-internal-tools), LuminaryCloud (@luminarycloudinternal/*), Reddit-style Voyager UI (voyager-web, searchresults), plus workspace/microsite scopes — all replaced by npm Security within a 12-minute window on 2026-07-10 02:57–03:10 UTC. A smaller tail of nodemon-* / chai-redirection / paperclip-adapter-helpers typosquats and 2026-07-09 throwaways (none123s, tslint-conf) rounds out the sweep.
- Detected by
- GitHub Advisory Database · npm Security
- Also known as
- 2026-07-09 GHSA npm sweep · 2026-07-10 GHSA npm sweep · Epic Games dep-confusion burst
- Ecosystems
- npm
- Packages tracked
- 25
What happened
Between 2026-07-09 and 2026-07-10 GitHub's Advisory Database published 25 CWE-506 (Embedded Malicious Code) advisories against npm packages. Every record uses the standard "any computer that has this package installed or running should be considered fully compromised — rotate all secrets from a different computer" boilerplate. No payload write-ups accompany the GHSA texts, so defenders should treat install-time behavior as unanalyzed and assume worst case for any host that resolved these names.
The defining feature of this sweep — unlike the pure-typosquat runs of 2026-07-06, 2026-07-07, and 2026-07-08 — is that the majority of the 20 packages taken down on 2026-07-10 are dependency-confusion attempts against named enterprise internal namespaces, published and replaced within a tight 12-minute window (02:57–03:10 UTC).
Cluster 1 — Epic Games / Unreal Engine internal build-tooling cluster (5 packages)
robomerge, unreal-horde-dashboard, ue-jenkins-buildkite, ue-automation-scripts, epic-internal-tools. All five were replaced with 0.0.1-security between 2026-07-10 03:01:55 and 03:02:15 UTC — a 20-second replacement burst indicating the whole cluster was reported and taken down as a unit.
The naming space is not random — it directly mirrors Epic Games' public documentation for their internal build automation:
- Robomerge is Epic's Perforce-based automated code merge system, documented publicly at dev.epicgames.com.
- Horde is Epic's CI/build orchestration platform, documented for Unreal Engine licensees.
- UE-Jenkins-Buildkite and UE-Automation-Scripts match Epic's Unreal Engine automation naming conventions.
- Epic-Internal-Tools is the most on-the-nose slug — a generic catch-all internal namespace.
This is a canonical Alex Birsan-style dependency-confusion attack. The operator has clearly enumerated Epic Games' public build-tooling documentation and registered every plausible internal package name. Any Epic Games team or Unreal Engine licensee running an internal npm registry — with the fall-through to the public registry misconfigured — would have silently pulled these malicious versions on the next npm install.
Cluster 2 — LuminaryCloud internal-scope cluster (2 packages)
@luminarycloudinternal/lcvis-st (replaced 2026-07-10 03:10:00 UTC), @luminarycloudinternal/frodo (replaced 2026-07-10 03:09:51 UTC). LuminaryCloud is a physics-simulation SaaS company (founded 2020, acquired attention in the CFD / mesh-simulation space). The @luminarycloudinternal scope is not a legitimate public npm scope — a scope-prefixed name of this shape is the strongest possible signal of a dependency-confusion attempt, since scoped packages resolve exactly against the scope namespace.
Same operator playbook as the Epic Games cluster: enumerate a target org, guess plausible internal package names under a shared scope, publish squats at a version high enough to win the resolver race against internal releases. lcvis-st reads like a "Luminary Cloud Visualization Streaming" module; frodo is a common internal code-name.
Cluster 3 — Reddit-adjacent Voyager UI cluster (2 packages)
voyager-web (replaced 2026-07-10 03:00:04 UTC), searchresults (replaced 2026-07-10 02:59:58 UTC). "Voyager" is Reddit's React-based frontend framework, the successor to the classic reddit.com "Old Reddit" stack. The voyager-web name is a highly plausible internal package name for Reddit's web-app codebase; searchresults is a generic-but-plausible internal helper for a search UI component.
Both published within 10 seconds of each other and replaced together — same operator, same targeted enumeration approach as the Epic cluster.
Cluster 4 — Generic microsite / workspace scopes (3 packages)
@businessapp-microsites/apis (replaced 2026-07-10 02:58:14 UTC), workspace-scripts (02:58:01 UTC), workspace-lint (02:57:56 UTC). All three published in a 20-second window immediately before the Voyager cluster. The @businessapp-microsites scope pattern matches enterprise CMS/microsite tooling (a common naming convention for multi-tenant SaaS platforms). workspace-scripts and workspace-lint are generic monorepo helper names — plausible under @your-org/workspace-scripts, and if an internal npm mirror is misconfigured they could resolve unscoped against the public registry.
Cluster 5 — nodemon typosquat family (3 packages)
nodemon-patch (2026-07-10 02:54:57 UTC), nodemon-gulp (2026-07-10 02:46:28 UTC), nodemon-sudo (2026-07-09 12:34:15 UTC). Direct typosquats of nodemon, one of the top-100-installed dev packages on npm (~10M weekly downloads). The nodemon-<verb> pattern targets developers who assume a companion helper exists — canonical nodemon configuration is done via nodemon.json or CLI flags, and there are no first-party sidecar packages.
Cluster 6 — Chai matcher continuation
chai-redirection (replaced 2026-07-10 02:57:03 UTC). Direct continuation of the Chai matcher-squat theme from the 2026-07-06 chai-as-* cluster and 2026-07-07 chai-sdk / chai-spycore / chai-chain-dom cluster. The chai-<matcher-name> pattern targets developers extending Chai assertions with a plausible-sounding matcher name.
Cluster 7 — Miscellaneous typosquats and throwaways
paperclip-adapter-helpers(2026-07-10 02:36 UTC) — Paperclip framework typosquat; the canonical asset-uploader lib is Rails-sidepaperclip(Ruby), no first-party JS.nodepack-daemon(2026-07-10 02:44 UTC) —nodepacksquat.crypto-promiser(2026-07-10 02:42 UTC) — Node.jscryptohelper squat; the canonical lib is the built-incryptomodule ornode:crypto.vps-new-manager(2026-07-10 02:36 UTC) — Generic VPS management tool squat.cursed-ecto-d3ab00(2026-07-10 03:08 UTC) — Elixir Ecto ORM squat with a random 6-hex-char suffix (d3ab00). The suffix pattern indicates an attacker-generated random slug, likely to evade takedown detection by not registering as a "sensible" name.txs-builder-lib(2026-07-09 14:38 UTC) — Blockchain transaction-builder squat; targets any Web3-adjacent naming space.tslint-conf(2026-07-09 12:34 UTC) — TSLint config squat. TSLint has been officially deprecated since 2019 in favor of ESLint; anyone still resolving TSLint packages is on legacy code.none123s(2026-07-09 14:44 UTC) — Throwaway name with no obvious target.@kl-starfish/test-01(2026-07-09 22:08 UTC) — Throwaway scoped test package. Notable because as of the 2026-07-10 03:00 UTC replacement burst, this one was NOT replaced (still resolves to2.0.0on the registry) — GHSA classification but no npm-side yank yet.
Contrast with recent sweeps
| Date | Packages | Notes | |---|---|---| | 2026-07-02 | 9 | Tailwind + db-* cluster | | 2026-07-03 | 14 | TypeScript / API family + @sql-* scopes | | 2026-07-06 | ~155 | Largest 2026 sweep | | 2026-07-07 | ~65 | AI-SDK typosquats + Solana base58 | | 2026-07-08 | ~20 | Claude-Code typosquat cluster | | 2026-07-09 / 2026-07-10 | 25 | Epic Games / LuminaryCloud / Voyager dep-confusion + nodemon family |
The running July 1–10 npm-malware retirement count is ~295 packages across 8 GHSA sweeps — a step-change in the platform's take-down cadence.
Registry state and version notes
Every package except @kl-starfish/test-01 now resolves to a 0.0.1-security holding tarball owned by npm Security. Because the security replacement wipes the historical version list from the public registry response and OSV was unreachable at ingest time, the exact pre-replacement malicious version numbers for each package are not fully recoverable from primary sources. The version list below records the plausible dep-confusion version (99.9.9, the observed convention across the 2026-06-29 internal-scope cluster and Sonatype's 176-package campaign) for the dep-confusion cluster and a common 1.0.0 placeholder for the typosquats. Historical version tarballs may remain fetchable from the CDN for 24–72 hours after the security replacement lands and should be treated as live malware in any lockfile hit — regardless of exact version.
Affected packages (25)
- npm
@businessapp-microsites/apis99.9.9 - npm
@kl-starfish/test-012.0.0 - npm
@luminarycloudinternal/frodo99.9.9 - npm
@luminarycloudinternal/lcvis-st99.9.9 - npm
chai-redirection1.0.0 - npm
crypto-promiser1.0.0 - npm
cursed-ecto-d3ab001.0.0 - npm
epic-internal-tools99.9.9 - npm
nodemon-gulp1.0.0 - npm
nodemon-patch1.0.0 - npm
nodemon-sudo1.0.0 - npm
nodepack-daemon1.0.0 - npm
none123s1.0.0 - npm
paperclip-adapter-helpers1.0.0 - npm
robomerge99.9.9 - npm
searchresults99.9.9 - npm
tslint-conf1.0.0 - npm
txs-builder-lib1.0.0 - npm
ue-automation-scripts99.9.9 - npm
ue-jenkins-buildkite99.9.9 - npm
unreal-horde-dashboard99.9.9 - npm
voyager-web99.9.9 - npm
vps-new-manager1.0.0 - npm
workspace-lint99.9.9 - npm
workspace-scripts99.9.9
Impact
- Any host that installed any of the 25 packages listed below should be treated as fully compromised — every GHSA record uses the boilerplate CWE-506 "rotate all secrets from a different computer" language, and no patched version exists for any of them
- Epic Games / Unreal Engine internal-scope cluster (5 packages:
robomerge,unreal-horde-dashboard,ue-jenkins-buildkite,ue-automation-scripts,epic-internal-tools) — the naming space directly matches Epic's public documentation for their Perforce merge automation (Robomerge), Horde build system, and their internal Jenkins/Buildkite pipelines. This is a classic Alex Birsan-style dependency-confusion attempt: any Epic Games or Unreal Engine licensee running an internal npm registry with a package of these names would silently pull the public malicious version on the next resolver run - LuminaryCloud internal-scope cluster (2 packages:
@luminarycloudinternal/lcvis-st,@luminarycloudinternal/frodo) — LuminaryCloud is a physics-simulation SaaS provider; the@luminarycloudinternalscope is not a legitimate public scope. Anyone at LuminaryCloud running a private registry mirror with a package under@luminarycloudinternal/*would have resolved the malicious public version if the mirror was misconfigured - Reddit-adjacent Voyager cluster (2 packages:
voyager-web,searchresults) — "Voyager" is Reddit's in-progress React-based frontend framework (successor to the classic reddit.com stack);searchresultsis a plausible internal helper name. Both published within 10 seconds of each other at 2026-07-10 03:00 UTC and taken down together - Generic microsite/workspace cluster (3 packages:
@businessapp-microsites/apis,workspace-scripts,workspace-lint) — the@businessapp-micrositesscope pattern matches enterprise CMS/microsite tooling naming;workspace-scriptsandworkspace-lintare common monorepo helper names - nodemon typosquat family (3 packages:
nodemon-patch,nodemon-gulp,nodemon-sudo) —nodemonis one of the most-installed dev-time packages on npm (~10M weekly downloads). Thenodemon-<verb>pattern targets developers who add nodemon plus a companion package. The canonical companion pattern isnodemon.jsonconfig or--execflags, NOT sidecar packages - Miscellaneous typosquats and throwaways —
chai-redirection(Chai matcher squat continuation from the 2026-07-06 and 2026-07-07 chai cluster),paperclip-adapter-helpers(Paperclip framework typosquat),nodepack-daemon(nodepack squat),crypto-promiser(Node crypto helper squat),vps-new-manager(server-tooling squat),cursed-ecto-d3ab00(Elixir Ecto ORM squat with a random 6-hex-char suffix — attacker-generated random-looking slug),txs-builder-lib(blockchain transaction-builder squat),tslint-conf(deprecated TSLint config squat),none123s(throwaway name),@kl-starfish/test-01(throwaway scoped test) - No payload write-up accompanies the GHSA texts — defenders should treat install-time behavior as unanalyzed and assume worst case for any host that resolved these names. Combined with the 2026-07-08 sweep (~20 packages), 2026-07-07 sweep (~65 packages) and 2026-07-06 sweep (~155 packages), the running July 1–10 npm-malware retirement count is ~295 packages across 8 GHSA sweeps
What to do
- 1Grep every lockfile (
package-lock.json,yarn.lock,pnpm-lock.yaml) for each name in the packages map below. Any match is a supply-chain incident: rotate every credential the build runner could reach and re-image the build host - 2If you build with Unreal Engine or work at Epic Games: audit every internal Node.js project for imports of
robomerge,unreal-horde-dashboard,ue-jenkins-buildkite,ue-automation-scripts, orepic-internal-tools. These are dependency-confusion squats against your build-automation tooling. If your internal npm registry mirror was ever configured to fall through to the public registry, one of these could have resolved silently. Register the equivalent names as stubs on the public npm registry to prevent future squats, and route internal names via.npmrcscope pinning - 3If you work at LuminaryCloud: any dependency under
@luminarycloudinternal/*in a lockfile is malware. Rotate every credential reachable from any build host that ever resolved this scope. Register the@luminarycloudinternalscope on the public npm registry as a defensive stub - 4If your build ever resolved
voyager-weborsearchresults: audit whether an internal package of the same name should have won the resolver race. The Reddit "Voyager" project name may not be the actual target — the operator may have enumerated public Reddit docs and guessed at internal names - 5For the
nodemon-*cluster (nodemon-patch,nodemon-gulp,nodemon-sudo) — the canonical package isnodemon. There is no first-party nodemon companion package on npm; configuration is done vianodemon.jsonor CLI flags. Any nodemon sidecar in your lockfile should be reviewed - 6For
chai-redirection,paperclip-adapter-helpers,nodepack-daemon,crypto-promiser,vps-new-manager,cursed-ecto-d3ab00,txs-builder-lib,tslint-conf,none123s, or@kl-starfish/test-01— these are typosquats/throwaways with no legitimate parent. Any lockfile match should be treated as a compromise and the build host re-imaged - 7Register every internal
@scopeyou use on the public npm registry (even as a stub) so a future dependency-confusion squat under the same scope cannot resolve. Pin your registry: use.npmrcto route scoped names to your internal mirror only (e.g.@luminarycloudinternal:registry=https://internal/), so the public-registry path is never queried - 8Verify none of the 25 listed packages still resolves via your private mirror — internal Artifactory / Nexus / Verdaccio instances routinely cache tarballs and will keep serving the malicious versions after the public yank
References
- GitHubGitHub Advisory Database — recent npm malware advisoriesgithub.com
- GitHubGHSA-x22f-73cv-vccx — robomerge malware advisorygithub.com
- GitHubGHSA-vwh3-m8vq-24r2 — unreal-horde-dashboard malware advisorygithub.com
- GitHubGHSA-8gxq-wrp7-qqv8 — ue-jenkins-buildkite malware advisorygithub.com
- GitHubGHSA-g68g-mm68-67f5 — ue-automation-scripts malware advisorygithub.com
- GitHubGHSA-wx8q-h5p5-9hcf — epic-internal-tools malware advisorygithub.com
- GitHubGHSA-pgh8-mm8r-r796 — @luminarycloudinternal/lcvis-st malware advisorygithub.com
- GitHubGHSA-p92p-63h9-qrvc — @luminarycloudinternal/frodo malware advisorygithub.com
- GitHubGHSA-3vr9-xc7m-h6qx — voyager-web malware advisorygithub.com
- GitHubGHSA-cpff-p65h-24c4 — searchresults malware advisorygithub.com
- GitHubGHSA-5x2m-5wc4-5j3c — @businessapp-microsites/apis malware advisorygithub.com
- GitHubGHSA-pcrx-c762-59jm — workspace-scripts malware advisorygithub.com
- GitHubGHSA-2667-2whh-v3mf — workspace-lint malware advisorygithub.com
- GitHubGHSA-89c7-5mf7-c86r — chai-redirection malware advisorygithub.com
- GitHubGHSA-5v8m-v9mp-gf8h — nodemon-patch malware advisorygithub.com
- GitHubGHSA-wqr5-5c9r-9rj7 — nodemon-gulp malware advisorygithub.com
- GitHubGHSA-8228-4gjp-c339 — nodemon-sudo malware advisorygithub.com
- GitHubGHSA-v7fc-qvp5-6qx3 — nodepack-daemon malware advisorygithub.com
- GitHubGHSA-pgcc-398f-7cv2 — crypto-promiser malware advisorygithub.com
- GitHubGHSA-v3ch-6vv8-xr3w — paperclip-adapter-helpers malware advisorygithub.com
- GitHubGHSA-vm7q-854p-gw38 — vps-new-manager malware advisorygithub.com
- GitHubGHSA-9x5f-jcqq-j88c — cursed-ecto-d3ab00 malware advisorygithub.com
- GitHubGHSA-r4hr-3frr-jgjv — txs-builder-lib malware advisorygithub.com
- GitHubGHSA-wchw-4whx-qhq5 — tslint-conf malware advisorygithub.com
- GitHubGHSA-rqf4-7r8q-fxmq — none123s malware advisorygithub.com
- GitHubGHSA-q8q2-g7r6-wg9x — @kl-starfish/test-01 malware advisorygithub.com
- Epic GamesRobomerge documentation — Unreal Engine developer docsdev.epicgames.com
- Epic GamesHorde build system for Unreal Enginedev.epicgames.com