Security is an important aspect for development of all kinds of software, and Unity projects are no different. As part of Unity’s Responsible Disclosure policy, we work closely with external researchers on possible vulnerabilities or issues that arise within the Unity environment. Recently we have been in contact with security researchers at IncludeSecurity. Working with them in the model of coordinated disclosure, we want to share information about insecure development practices that Unity developers may encounter. The two topics covered in this blog post are dependency confusion and AssetBundle security.
Supply chain security vulnerabilities are a serious issue that all Unity developers need to take into consideration when creating their games.
One of these vulnerabilities is known as dependency confusion. Dependency confusion occurs when an attacker is able to influence a developer's environment and tools to download a malicious package. This attack leverages the use of unsafe default behavior within some package managers and private repositories.
The Unity Editor has its own package manager, Unity Package Manager, which supports fetching packages from NPM registries. This means a Unity developer using a private NPM registry could face the same risks of the dependency confusion vulnerability described above.
Take for example, a Unity project that pulls from a private registry and a public registry like npm.io. A developer can upload Package A to the private registry, as a standard development practice. If the package manager scopes are too broad or if the private registry proxies a public registry, then a malicious attacker can upload a malicious Package A with a higher version number to the public repository. Due to its higher version number, the malicious package may be downloaded to the Unity project, which would result in code execution on the developer’s machine at dependency load time, or on any machines running the Unity project.
NOTE: Unity does not recommend using public registries, such as the NPM public registry. Many packages in these public repositories are not supported in the Unity editor, and some features are not supported by the Unity Package Manager.
By using private packages in the Unity editor with a private registry that proxies a public repository, a developer may leave themselves vulnerable to a dependency confusion attack. This attack is what IncludeSecurity describes in their article here.
IMPORTANT: The default configuration of the Unity Package Manager is not vulnerable to a dependency confusion vulnerability. The developer must modify their manifest.json file, as detailed below, to become vulnerable. See below in the ‘Mitigations’ section to understand if you’ve modified your local package configuration in a vulnerable manner, and how to update your configuration to mitigate the vulnerability. The vast majority of developers should not be concerned, but should familiarize themselves with content nonetheless, in order to understand how they can continue to keep their codebase and customers protected.
In the example vulnerable configuration below, a proxied registry is used as the only scoped registry, one that pulls from the private registry and from the public NPM registry. Since the packages defined in the scope share the same registry, a malicious attacker can upload “com.private.vulnerable.package” with a higher version to the NPM registry, which can result in the malicious package being downloaded to the user’s environment when the developer updates their packages.
Example Vulnerable Configuration:
The typical mitigations such as scoped packages for NPM are not supported in Unity Package Manager. Instead, using Scoped Registries can prevent this type of issue. By explicitly defining packages in the scopes of a scoped registry, the source of the package will be strictly locked down to what is defined in the scoped registry configuration file.
Note that if a private registry also proxies NPM, then the Unity Package Manager cannot differentiate between a private published package or publicly published one. The mitigation needs to be applied at the registry level, which IncludeSecurity describes in their article.
The following configuration fixes the vulnerable configuration by splitting the registries into their own scoped registry blocks, and explicitly defines which packages are used by each registry. This means a malicious package will not be downloaded into the user’s environment, even if the package has a higher version on a public registry.
Example Secure Configuration:
AssetBundles are a commonly used feature in the Unity engine that are used to deliver assets in a standardized format. They are commonly used to download additional assets to a user’s game when the asset is needed, cutting down on the amount of data required to be initially downloaded to play a game. In some cases, AssetBundles can even be used to distribute custom content for modding or customization in a Unity project.
When using AssetBundles, it is important that they are downloaded from a trusted source. Even though AssetBundles cannot contain executable code, IncludeSecurity found that a specially crafted AssetBundle file could allow an attacker to exploit a vulnerability in the game code or the Unity runtime. This is the issue described by IncludeSecurity.
As such, AssetBundles that are downloaded off the internet should be treated no differently than any other piece of software that is downloaded from the internet:
As content creators, there are risks associated with the tools and services that are relied upon to help create amazing experiences. Taking the time to ensure that your own developer toolchain is secured and configured properly will provide the benefit of security to both yourself and your users.