Strictest Content-Security-Policy for Unity games

Introducing a Content-Security-Policy on any pre-existing application host is generally a process of trial and error. As Unity projects lay out and load assets in a specific way, we were hoping for an official guide outlining a good setup for strict Content-Security-Policy directives. We found neither an official nor unofficial summary of the situation. The following is our best guess, synthesized from Unity support answers and our own experiments.

The core requirements are to evaluate WebAssembly and scripts from blob: URLs. To avoid allowing inline scripts, the WebGL templates need to be adjusted. This requires a small workaround in Unity versions older than 2020.1.

Theoretical baseline: WebAssembly and blob: URLs

At the time of writing, the strictest theoretical script source directive that will allow Unity games to run is

script-src blob: 'wasm-unsafe-eval' 'self';

which allows blob: URLs and WebAssembly (and assuming the scripts are hosted on the same server as the HTML document, hence 'self').

Practical baseline: Eval and blob: URLs

The wasm-unsafe-eval keyword is part of CSP Level 3 and has only recently landed in some major browsers. An estimated 79 % of users are currently using compatible browsers. Previous versions lump evaluation of WebAssembly in with evaluation of other JavaScript. To support slightly older browser installations, it may therefore be necessary to relax the directive to

script-src blob: 'unsafe-eval' 'self';

Avoiding inline scripts in Unity 2019.4 and older

Unity in version 2019.4 is only able to fill in template variables in an index.html file (see the 2019.4 manual). The manual recommends an inline script to capture and use the BUILD_URL variable. When following this recommendation, 'unsafe-inline' must be allowed as script-src.

To avoid this, we can instead write the build variable’s contents to a data attribute on the game container and read it from an external main.js.

<div id="container" data-build-url="%BUILD_URL"></div>
<!-- ... -->
<script src="%UNITY_WEBGL_LOADER_URL%"></script>
<script src="main.js"></script>
Excerpt from index.html
var container = document.getElementById("container");
var unityInstance = UnityLoader.instantiate(container, container.dataset.buildUrl);
Minimal main.js

Avoiding inline scripts in Unity 2020.1 and newer

According to the manual for version 2020.1 and later, Unity now processes JavaScript files in WebGL templates. It should thus be possible to use the template variables directly in external JavaScript files.


We hope that this little summary will save somebody some research work. We thank Malachi from Unity’s support team for checking some of our hypotheses with their technical team.