Dependency Confusion Attacks: How Supply Chain Exploits Compromise Your Code

Written by the Rafter Team

Dependency confusion is a supply chain attack that tricks package managers into installing a malicious public package instead of the intended private one. Attackers publish packages to public registries like npm or PyPI using names that match internal company packages, often with inflated version numbers. When a build system resolves dependencies, it pulls the attacker-controlled package because the public registry takes priority. Your CI pipeline executes the malicious code automatically during installation.
How Dependency Confusion Works
Package managers follow a resolution order when fetching dependencies. If your project references @acme/auth-utils but your .npmrc does not explicitly scope that namespace to a private registry, npm checks the public registry first. An attacker who publishes auth-utils at version 99.0.0 to the public npm registry wins the version comparison. The malicious package runs its postinstall script with full access to your build environment.
Alex Birsan demonstrated this attack in 2021 against Apple, Microsoft, and PayPal. He published packages matching internal dependency names and achieved code execution on internal build servers at all three companies.
A single unscoped internal package name is enough for an attacker to execute arbitrary code in your build pipeline. If you maintain private packages, audit your registry configuration now.
Typosquatting and Package Takeover
Typosquatting targets developers who mistype package names. Attackers register names like expresss, loadsh, or cross-env2 and embed credential stealers or cryptominers. You install the wrong package and the malicious code runs before you notice the typo.
Package takeover is more dangerous. In 2018, the maintainer of event-stream (over two million weekly downloads) handed control to a new contributor who injected a targeted cryptocurrency-stealing payload. The malicious code sat in production for weeks before discovery. In 2021, ua-parser-js was compromised through a hijacked maintainer account, pushing cryptomining malware to millions of downstream projects.
The xz Utils backdoor in 2024 showed how patient attackers can be. A contributor spent two years building trust before inserting a sophisticated backdoor into the compression library, targeting SSH authentication on Linux systems. The backdoor was discovered by accident.
Defending Against Supply Chain Attacks
Scope Your Registries
Configure your package manager to resolve private packages exclusively from your internal registry. In npm, set scoped registries in .npmrc:
@acme:registry=https://registry.internal.acme.com/
This ensures any package under @acme/ never resolves against the public npm registry. Every internal package should use an organization scope.
Pin Dependencies with Lockfiles
Commit your package-lock.json, yarn.lock, or pnpm-lock.yaml to version control. Lockfiles pin exact versions and integrity hashes. If an attacker publishes a new version, your build still installs the version recorded in the lockfile. Review lockfile diffs in every pull request.
Run SCA with Malicious Package Detection
Standard SCA tools check for known CVEs, but dependency confusion and typosquatting require malicious-package detection. Look for SCA tools that flag suspicious package names, anomalous publish patterns, and known-malicious maintainer accounts.
Scan your dependencies for supply chain threats with Rafter -- detect malicious packages and vulnerable dependencies before they reach production.
Additional Hardening
- Use
--ignore-scriptsduring CI installs to preventpostinstallexecution, then run scripts explicitly for trusted packages only. - Enable npm provenance to verify that packages were built from their linked source repositories.
- Audit new dependencies before adding them. Check download counts, maintainer history, and repository activity.
- Monitor for namespace squatting on public registries if your organization uses unscoped internal packages.
Stop Supply Chain Attacks Before They Ship
Dependency confusion, typosquatting, and package takeover exploit the trust you place in your dependency tree. Automated scanning catches what manual review cannot. Combine scoped registries, lockfile discipline, and continuous SCA to close these gaps.
Start scanning your supply chain with Rafter -- get visibility into every dependency across your repositories in under two minutes.