New package management flaw: dependency confusion

Typosquatting package managers is a familiar and well-documented security issue that targets developers who misspell dependencies. However, recent research has demonstrated a similar yet much more prevalent user security misconfiguration in several popular package managers, dubbed dependency confusion.

A team of researchers disclosed this vulnerability and managed to exploit several global companies, including Paypal, Microsoft, Apple, Netflix, Shopify, Yelp and Uber. They received bug bounty payouts totalling over $130,000.

The vulnerability

When a mix of local and remote packages are included in a build, some package managers will attempt to download each package from the public remote server before checking local repositories. Any packages that are expected to be local-only could be overridden by uploading a package of the same name to the remote repository. This will largely affect packages that are built by organizations and not publicly available.

The following package managers are known to be affected:

  • NPM
  • RubyGems
  • PyPi
  • JFrog
  • NuGet

Example: vulnerable Python configuration

The example below shows a typical requirements.txt that can be used to pull Python packages from the PyPi repository.

A vulnerable Python requirements.txt file

This configuration is vulnerable to a dependency confusion attack because the flask-auth-company-name is a local-only dependency that is not expected to exist in the remote repository.

The exploit

The exploit itself is easy to perform but there are several obstacles that need to be overcome. Firstly, an attacker must identify or exact the name of a package in use by the target company. Realistically, an attacker also needs to obtain the package – or even better, its source code. This allows them to create a malicious package that doesn’t cause immediate suspicion from builds or software failure.

An attacker can then upload the malicious package using the obtained name, ensuring it has a higher version number than that of the local package. The next time the build process is called, the malicious package gets downloaded from the repository and used instead of the local package.

These malicious packages are capable of infecting any build system or server they are installed on. This is an example of a supply chain compromise, similar to that seen in the SolarWinds attacks.


If your organization uses internally developed packages and any of the affected package managers, you need to mitigate this attack.

Most mitigations depend on which package manager is used. Microsoft has published a comprehensive whitepaper which details steps that can be taken to mitigate dependency confusion. The main points are:

  1. Avoid a hybrid approach and use only a single private repository. This can still pull in packages from a public repository but provides you with complete control of which packages it pulls.
  2. If supported by the package manager, always specify scopes to define where packages should be pulled from (currently only for NPM and NuGet).
  3. Use client-side validations, such as version pinning and integrity verification.

Try it yourself

If you have an Immersive Labs licence, you can try your hand at performing a dependency confusion attack against a build server in our latest infrastructure hacking lab. In this lab, you’ll analyse and compromise a target build server by writing and uploading a malicious Python package. Log in here.

If you don't have a licence for Immersive Labs, why not book a demo to get a guided tour of our platform?


22 February 2021

Mat Rollings,
Senior Application Security Engineer

We help businesses to increase and evidence human capability in every part of cybersecurity.