Adobe Commerce (Magento2). Dependency Confusion security vulnerability

Magento 2 and Adobe Commerce web applications are built using a combination of in-house custom code and third-party libraries. The first-party(in-house) code leverages functionality from typically open-source Also Magento has 3-d party libraries installed via composer. These modules will typically be deployed to the webserver serving the web application along with the in-house code.

The packages are most commonly downloaded from public registries such as Packagist taking advantage of the open-source ecosystem. It is also common for organizations to utilize private registries to mirror the public index or distribute internal packages which cannot be published publicly. The most famous is magento.repos and each 3-d party extension vendor also has its own repo. Package management tools composer allows specifying multiple sources from which to download components.

Relying on these public feeds introduces a vector for so-called supply chain attacks which can result in remote code execution if installed dependencies contain malicious code. This is because the included libraries execute within the same trusted context as the in-house code that loads them, or within the build context when installing the dependency.

Also, an attacker may be able to infect a legitimate package for example by submitting a pull request to the maintainer that contains malicious code while appearing to be benign, or compromising the build process for the legitimate package.

Recently Alex Birsan published an article highlighting the behaviour of some package managers when selecting which source to use when a package with the same name is available from both a private and a public registry. His research showed that npm, gems, and pip (and potentially other package managers) would select the package with the highest version number (as opposed to defaulting to the private registry as may be intended). This can lead to a critical security vulnerability when the package name is unregistered on the public feed since an attacker can register the name along with a very high version number, which causes the package manager to select the malicious package from the public registry rather than the legitimate package (with a lower version number) from a private registry. Alex has dubbed this issue Dependency Confusion, however you may see it referred to as Supply Chain Substitution Attacks.

To exploit dependency confusion via this vector, an attacker must discover or guess a package name that is used internally by an organisation, but which is unregistered to date on the public registry. One method of accomplishing this for Composer is to analyse the composer.json file if it is disclosed by the application (this is often accidentally published to the web server when deploying an application in what might appear to be a relatively benign information disclosure vulnerability).

A composer.json file looks something like this (truncated for brevity):

The packages names can then be checked against the public Packagist composerregistry to identify unregistered packages, or scopes (note that an attacker cannot publish a package under a registered scope they do not control even if the package under that scope does not exist).

Composer 2.0 has several mitigations in place to help protect against Dependency Confusion attacks as described in their article: https://blog.packagist.com/preventing-dependency-hijacking/. Composer strictly enforces a vendor prefix for all package names which is restricted to the first maintainer to publish a package using that prefix on packagist.org. Additionally, if a repository is configured for a package, it is treated as canonical, preventing the public registry from being searched.

However, errors in configuration may allow successful attacks if the vendor prefix has not been claimed: for example, if the package name is not correctly associated with a repository (such as a spelling error in the package name) an attacker could publish a package that would be used by the misconfigured system.