npm Dependency Confusion Targets Internal Package Names
Malicious npm packages logged on 2026-07-10 use dependency confusion, copying internal package names that match Epic, LinkedIn and Luminary Cloud.
On 2026-07-10 our catalog logged 20 new critical entries for malicious npm packages, and the names tell the story. Several of them copy the private, internal package names that only exist inside specific engineering organizations: voyager-web, robomerge, epic-internal-tools, unreal-horde-dashboard, and two packages under the @luminarycloudinternal scope. That is the signature of dependency confusion, an attack where someone publishes a public package using the exact name of a company's private one, hoping a misconfigured install pulls the public copy instead. When it works, attacker code runs inside that company's developer machines or CI pipeline.
We were not able to find a single named vendor writeup that ties this specific cluster together at publication time. What we can document is concrete: the package names, the fact that each was flagged as malware, and the technique those names point to. The mechanics and defenses below draw on well-documented dependency confusion campaigns from earlier in 2026, which used the same playbook.
What happened
The 20 packages catalogued on 2026-07-10 fall into three groups. The first, and the reason this cluster is worth writing up, is internal-namespace impersonation. The second is classic typosquatting of popular libraries. The third is generic bait with crypto or infrastructure themes.
The internal-namespace group is the interesting one because those names are not guessable. You do not know a company runs a package called robomerge or unreal-horde-dashboard unless you have seen their private registry, their build scripts, or a leaked package.json. RoboMerge is Epic Games' Perforce branch integration bot. Horde is Epic's build and automation system for Unreal Engine. The ue- prefix maps to Unreal Engine. voyager-web matches the long-standing internal name for LinkedIn's front-end codebase. The @luminarycloudinternal scope names itself as internal. Publishing public packages with those exact names is a deliberate move to catch installs inside those organizations.
This mirrors a run of campaigns from May 2026. Microsoft Threat Intelligence documented 33 malicious packages published across nine organizational scopes that copied real internal corporate namespaces, several of them even spoofing internal GitHub Enterprise, Jira, and documentation URLs in their package.json to look legitimate. In parallel, Sonatype analysed a 176-package campaign built specifically to shadow companies' internal dependencies. The July 10 cluster is smaller but uses the same idea.
Which package names showed up
Grouped by what the names appear to mirror. Treat the company associations as inference from naming, not confirmation that any of these companies were breached. Dependency confusion targets a company's developers and build systems, it does not require access to the company at all.
Unreal Engine and Epic Games tooling: epic-internal-tools, robomerge, unreal-horde-dashboard, ue-automation-scripts, and ue-jenkins-buildkite.
Other internal-looking names: voyager-web, @luminarycloudinternal/lcvis-st, @luminarycloudinternal/frodo, @businessapp-microsites/apis, workspace-lint, workspace-scripts, nodepack-daemon, searchresults, and paperclip-adapter-helpers.
Typosquats of popular libraries: nodemon-patch and nodemon-gulp both trade on nodemon, and chai-redirection trades on the chai assertion library.
Generic bait: crypto-promiser, vps-new-manager, and the random-looking cursed-ecto-d3ab00.
The five critical entries from the day before (2026-07-09) fit the same shape: airkey-mfa-react, security-console-ui, bizapi-portal, calvuepro, and clavue-agent-sdk. We have not confirmed the two days are the same operator.
We do not have verified download counts, command-and-control indicators, or a maintainer alias for this specific cluster. If those surface, we will update the individual incident pages.
How the dependency confusion attack works
The failure mode is old and well understood. When a package manager resolves a name that exists both in your private registry and on the public npm registry, some configurations pick whichever version number is highest. An attacker who knows your private package voyager-web sits at version 2.3.1 publishes a public voyager-web at 99.0.0, and the resolver happily grabs the public one. Snyk's writeup on the technique describes this exact scope-and-version confusion as the core of the attack.
Once the wrong package installs, the payload usually runs through a lifecycle hook. In the May 2026 dependency confusion campaign, Microsoft traced the chain as npm install triggering a postinstall script, which fetched an obfuscated payload from a C2 server, wrote it to a temp directory, and spawned a detached process that exfiltrated environment variables and credentials. Unit 42 has tracked the same 2026 pattern across many campaigns, with the recurring goal of stealing npm tokens, GitHub Personal Access Tokens, and cloud credentials so the attacker can pivot deeper or republish more packages.
Two things make internal-name targeting nastier than random typosquatting. The install often lands on a developer workstation or CI runner that already holds cloud and registry credentials. And the names are specific enough that a hit is a strong signal the attacker reached the intended target, not a stranger.
The dependency confusion wave in 2026
This is not the first cluster of its kind this year. A campaign against Genoma UI and related internal names was reported in April 2026. On 28 and 29 May 2026, Microsoft documented two waves: 14 typosquatted packages built to steal AWS, HashiCorp Vault, and CI/CD secrets, and 33 dependency confusion packages across nine corporate scopes, including one that impersonated a bank's payment widget. Sonatype's 176-package analysis landed in the same window. The July 10 entries continue that cadence rather than starting something new.
Who is affected
Directly, anyone running npm, pnpm, or yarn in a repository or pipeline that references one of these names and resolves it against the public registry. That includes organizations that own private packages with matching names and have not scope-locked their registry configuration.
Named organizations whose internal tooling the names appear to mirror are not necessarily compromised. The whole point of dependency confusion is that the attacker never needs to touch the company. They only need one of the company's developers or CI jobs to fetch the public copy by mistake.
How to check if you are affected
Search your lockfiles and installed tree for the flagged names. Start with the unscoped packages.
grep -nE "voyager-web|robomerge|unreal-horde-dashboard|ue-jenkins-buildkite|ue-automation-scripts|epic-internal-tools|nodepack-daemon|workspace-lint|workspace-scripts|chai-redirection|nodemon-patch|nodemon-gulp|crypto-promiser|paperclip-adapter-helpers|vps-new-manager|searchresults|cursed-ecto-d3ab00" \
package-lock.json yarn.lock pnpm-lock.yaml npm-shrinkwrap.json
Then the scoped ones.
grep -nE "@luminarycloudinternal/|@businessapp-microsites/" \
package-lock.json yarn.lock pnpm-lock.yaml
If any match, confirm which registry actually served the package. A resolved URL that points at registry.npmjs.org for a name you believe is private is the tell.
npm ls voyager-web robomerge epic-internal-tools 2>/dev/null
npm view voyager-web dist.tarball
Check CI logs for install steps on runners between 2026-07-08 and now, and look for outbound network connections from build agents that do not match your normal baseline.
Remediation and prevention
If you find an install, treat the affected workstation or runner as compromised. Remove the package and its node_modules entry, then rotate every credential that machine could reach: npm tokens, GitHub PATs, cloud keys (AWS, GCP, Azure), Kubernetes service account tokens, and CI/CD secrets. This is the same guidance CISA gave for the Axios compromise, and it applies here.
Lock every internal scope and name to your private registry so the public registry is never a fallback. Put this in .npmrc and commit it.
@luminarycloudinternal:registry=https://registry.internal.example.com/
@businessapp-microsites:registry=https://registry.internal.example.com/
Register your internal unscoped names defensively on the public registry, or move internal packages under a scope you control so a public collision is impossible. Turn off install scripts and add a release cooldown so brand-new versions cannot land in a build the moment they are published.
npm config set ignore-scripts true
npm config set min-release-age 604800
Use npm ci against a reviewed lockfile rather than npm install in CI, and fail builds that try to resolve an internal name from the public registry. pnpm and Yarn Berry offer equivalent lifecycle-script and cooldown controls if you prefer client-side enforcement.
FAQ
What is dependency confusion in npm?
It is an attack where someone publishes a public npm package using the same name as a company's private, internal package. If a developer or CI job resolves that name and the resolver prefers the higher public version number, it installs the attacker's package instead of the internal one. The public copy then runs its payload, usually through a postinstall hook.
Is voyager-web or robomerge safe to install from npm?
No public package by those names should be treated as your internal one. Both were flagged as malware in our catalog on 2026-07-10. If your project pulls a package with either name, verify it resolves to your private registry, not registry.npmjs.org, and pin the known-good internal version.
How do I know if I am affected by this cluster?
Grep your lockfiles for the names listed above and confirm the resolved registry for any match. If an internal name resolved from the public registry, or an install ran on a developer machine or CI runner in the exposure window, assume credentials on that host are exposed and rotate them.
Does SLSA provenance protect against dependency confusion?
Not on its own. Provenance tells you a package really was built by a given pipeline, but a malicious public package published with a copied name can still carry valid provenance for the attacker's own build. Earlier 2026 campaigns showed provenance and post-publication scanning both lag the speed of these attacks, which is why scope-locking and cooldowns matter more here.
Related catalog entries
- malware-in-cursed-ecto-d3ab00-hwtmc7
- malware-in-nodemon-patch-6rbmw6
- malware-in-businessapp-microsites-apis-1miqb7
- malware-in-epic-internal-tools-0s3gf5
- malware-in-robomerge-1afhsq
- malware-in-searchresults-5yawge
- malware-in-workspace-lint-2xylul
- malware-in-chai-redirection-u01wn8
- malware-in-nodemon-gulp-zvvnab
- malware-in-nodepack-daemon-s7ioq9
- malware-in-crypto-promiser-1mte0k
- malware-in-luminarycloudinternal-lcvis-st-1gof2u
- malware-in-luminarycloudinternal-frodo-1xnp1i
- malware-in-paperclip-adapter-helpers-150zc8
- malware-in-vps-new-manager-37slpw
- malware-in-ue-automation-scripts-h53x2r
- malware-in-ue-jenkins-buildkite-1wkf1f
- malware-in-unreal-horde-dashboard-nm0g0f
- malware-in-voyager-web-1ojo9g
- malware-in-workspace-scripts-1yngjx
Sources
- Malicious npm packages abuse dependency confusion to profile developer environments · Microsoft Security Blog
- Inside a 176-Package npm Campaign Built to Beat Your Internal Dependencies · Sonatype
- Detect and prevent dependency confusion attacks on npm · Snyk
- The npm Threat Landscape: Attack Surface and Mitigations · Palo Alto Networks Unit 42
- Supply Chain Compromise Impacts Axios Node Package Manager · CISA