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
.
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.