A security researcher named Alex Birsan recently wrote about a new type of attack called Dependency Confusion. Alex’s post gives a great overview of the attack, but provides little insight into mitigating this security risk. Here are some ways to identify if your development process is vulnerable to this attack and how to prevent it.
The Attack
Dependency Confusion happens during the build process for your application. Most modern software build processes use some form of dependency management solution to identify and download dependencies. This part of the build process downloads private dependencies stored in an organization’s private dependency repository. With the Dependency Confusion attack, instead of pulling in your private dependencies, the build is tricked into pulling in public dependencies that happen to have the same name.
For this attack to be successful, three conditions must be met:
- Part of your build process pulls in private dependencies
- The names of those dependencies are published externally
- Your build process can communicate with public package repositories at build time
How to mitigate Dependency Confusion
In order to mitigate this attack, we want to invalidate one or more preliminary conditions. Relying on private dependencies is desirable and a requirement for many projects, so we’ll focus on the other two.
First, do not publish the names of your private dependencies. In his writeup, Alex shows how he was able to use public information in order to create public packages with the same name as private packages. This “same name” quality allows the attack to succeed. Without knowing these package names, this attack would have been much harder.
Second, even if you do not publish the names of your private dependencies, ensure that your build is not attempting to resolve dependencies through public dependency repositories at build time.
- Force your dependency manager (pip for example) to only resolve from your dependency repository, never public dependency repositories.
- Once you have pinned your dependencies, disallow your dependency repository from proxying through to public dependency repositories.
This combination ensures that your dependencies will only ever be resolved through your known dependency repository.
Conclusion
As Alex’s article notes, there is no universal workaround for this type of attack. The exact solution for every dependency manager and dependency repository will look a bit different.
Large organizations with many dependencies and public repositories are particularly susceptible, but any organization with private dependencies and a build step that can reach public repositories is potentially at risk.
Locking down your dependency resolution to only your dependency repository and pinning versions mitigates this attack and will give your organization a generally improved security posture.