On this page
What Is Dependency Confusion (and How Do You Prevent It)?
Dependency confusion makes your build install a malicious public package instead of your private one. Learn how the attack works and how to pin it out.
Quick answer
- Dependency confusion installs a public malicious package when your build resolves a name that also exists in a private registry.
- It happens because package managers fetch the highest version across all sources, and public registries win over private ones.
- Prevent it with lockfiles, explicit registry scoping, and private-package allowlists — not by hoping names stay unpublished.
How does dependency confusion work?
Your project depends on an internal package that exists only in your private registry — say internal-auth. An attacker publishes internal-auth to the public npm registry with a higher version number. When your build resolves dependencies, the package manager checks all configured sources and picks the highest version, so it installs the attacker’s public copy instead of your private one. The malicious package runs arbitrary code during install or at import. Alex Birsan demonstrated this in 2021 against dozens of major companies by guessing internal package names and publishing them publicly.
Why are AI-generated projects especially exposed?
Vibecoded projects install packages liberally — the assistant adds dependencies on demand, often with vague or hallucinated names. If an assistant suggests a package name that happens to match an internal project (or an internal package that was never published), and the build pulls from the public registry, the confusion attack has its target. High install counts also attract typosquatters and name-squatters, who publish plausible-looking packages to harvest installs.
How do I prevent dependency confusion?
Layer the defenses: commit lockfiles so every install uses pinned, verified versions; scope private packages to your registry explicitly (registry scopes in npm, package sources in pip); tell the package manager to refuse public packages that collide with your internal naming; and use a private proxy registry (npm’s scoped registry, Artifactory, or similar) that checks a single source. If a name is already taken publicly, rename your internal package rather than hoping.
# npm: scope private packages to your registry only\n# .npmrc\n@mycompany:registry=https://npm.mycompany.com/\n# Then internal packages are installed only as @mycompany/*\n# and public squatting of the same name can't win the resolution.Where this bites vibecoders
This is the supply-chain attack most likely to reach a vibecoded app, because the setup has every ingredient: dependencies added by an assistant that doesn’t know what’s internal, no lockfile discipline, and installs that pull from the public registry. The fix is configuration, not code: lockfiles, scoped registries, and a rule that internal package names never look like public ones. It’s a ten-minute hardening pass with a very specific attack it kills.
Where AI coding assistants get this wrong
- Adding dependencies with vague or guessed names that could collide with internal packages.
- No lockfile, so builds resolve whatever version is newest on install day.
- Private packages installed from the public registry configuration by default.
- Assuming ‘our name is unlikely to be taken’ is a defense — attackers enumerate and squat.
Checklist
- Commit lockfiles and install from them in every environment.
- Scope private packages to your own registry and refuse cross-registry resolution.
- Scan installed packages for names that look like internal projects.
- Use a private proxy registry as the single source of truth for builds.
FAQ
How is dependency confusion different from typosquatting?
Typosquatting publishes a lookalike name (lodash vs l0dash) hoping you install it by mistake. Dependency confusion publishes the exact name of your private package, betting that the public copy wins version resolution. Confusion is more dangerous because the install looks correct.
Does a lockfile fully prevent dependency confusion?
A lockfile pins versions and integrity hashes, so a malicious package can’t be swapped in for one that’s already locked — but only if you review what enters the lockfile in the first place and use integrity checking. Lockfiles stop the silent swap; scoping and registry rules stop the confusion at resolution time.
Related topics
- What Is a Software Supply Chain Attack?
- What Is Slopsquatting (AI Package Hallucination Attacks)?
- What Is a Software Bill of Materials (SBOM)?
- How to Generate an SBOM for Your Project