Elixir Dependency Security: Mix, Hex, and Understanding the Ecosystem

Michael Lubas, 2023-01-24

Dependencies in a software project are a frequent source of security concern. The ability to detect outdated packages, and update to the latest version without breaking the project, is necessary for modern teams. In Elixir, dependencies are hosted by the Hex package manager, and managed by the Mix build tool. To better understand the ecosystem, let’s examine the different components in detail.

Mix - Elixir’s build tool. Mix manages the dependencies of an Elixir project, working together with Hex.

Hex - Hex is “The package manager for the Erlang ecosystem”. It is often used with Mix to install dependencies, for example the {:plug, "~> 1.1.0"} pattern is known to most Elixir developers. This Github repository stores the code that Hex runs locally on your computer.

hex.pm - The website where packages are hosted. For example, you can view statistics about how many people installed phoenix by visiting: https://hex.pm/packages/phoenix. The source code for the website is hosted on Github.

Mix and Hex documentation

When researching how to securely manage your Elixir’s project dependencies, remember that the relevant commands are documented across the two different projects, Mix and Hex:

Mix’s Mix Tasks:

Hex’s Mix Tasks:

Detecting and Updating Vulnerable Packages

As of January 2023, the best way to determine if your Elixir project’s dependencies have known vulnerabilities is with MixAudit, which compares your project’s dependencies with Github’s Elixir advisory database. It must be installed in your project’s mix file:

{:mix_audit, "~> 2.1"}

Sobelow is primarily a static analysis tool for Phoenix applications, meaning it examines the source code of a Phoenix project for vulnerable code. It also has the ability to detect vulnerable dependencies, which may lead to some confusion.

Using MixAudit and Sobelow together seems unnecessary if Sobelow can perform both tasks. However, Sobelow can only detect a few vulnerable dependencies hard-coded in its source, and this list has not been updated since 2021. If a new vulnerable package is reported to the Github advisory database tomorrow, Sobelow will not detect it, but MixAudit will. Sobelow is still the best tool for detecting vulnerable code in a Phoenix project, but is not recommended for the task of detecting vulnerable dependencies.

Hex also provides the mix hex.audit command, to show dependencies that have been marked as retired. The reason retired packages should not be included in a project is that, if a security problem is found in the retired package, there is no way to upgrade it. The entire package will have to be removed, or forked with the security patch. Removing the retired package as early as possible is the best way to proactively get ahead of security issues.

When a vulnerability is detected in a package, it needs to be upgraded. The reality of upgrading is that the changes may break your application. This process is easier if you practice regular updates of your packages, even when they are not vulnerable.

Dimitrios Zorbas wrote an excellent article on this topic, covering how to regularly upgrade your packages. For example, he recommends the following command:

mix hex.outdated --within-requirements 1>/dev/null || echo 'Updates available!'

to be included in continuous integration systems, to notify the owners when updates are available. The article also covers the diff tool, which is useful in high security environments, where every change needs to be manually reviewed for backdoors. For additional background on why diffing is useful in security, and how Hex’s diff feature was created, see the talk Diffing Hex packages by Johanna Larsson.

Summary of Security Related Mix Tasks

mix deps.audit 

List all packages with security vulnerabilities, requires MixAudit to be installed.

mix hex.audit 

List all retired packages. These packages do not necessarily have a security vulnerability, but are not maintained, and should be removed as soon as possible.

mix hex.outdated --all 

Check for outdated dependencies, will not make any changes to your project.

mix deps.update

Update a package, or all packages with the –all flag. This will make changes (destructive) and may break your application.

mix hex.package diff PACKAGE VERSION1 VERSION2

Fetch and diff two different versions of a package. Useful for security audits of package updates.

mix deps.tree

Prints the dependency tree of the current project. Supports CLI and graphical output.

mix sobelow

Scans the source code of your Elixir project for vulnerable code. Sobelow can also detect vulnerable dependencies, however relying on this feature is not recommend, because this list is hard-coded in the source, and has not been updated since April 2021. Using Sobelow for static analysis of a project’s source code is recommended, but for detecting vulnerable dependencies use MixAudit.

Paraxial.io stops data breaches by securing your Elixir and Phoenix apps. Detect and fix critical security issues today.

Subscribe to stay up to date on new posts.