While moving all inline scripts externally would take a tremendous amount of effort, as far as I can see, adding nonce-source support would be relatively trivial.
nonce-source works by adding a nonce
attribute to any <script>
tags you want to run, which is a base64 string randomly generated on each page load. This nonce is also added to the CSP header, and only scripts with the correct nonce set are allowed to run.
This means inline scripts can be whitelisted without the need to whitelist all inline scripts with unsafe-inline
, and external scripts can be included without the need to whitelist them explicitly in the header (which is useful for themes loading scripts from an external CDN).
More info:
To achieve this in Discourse we could generate the nonce on every page load in ApplicationController
, add it to request.env
so we can insert it where we want, and set the appropriate CSP header (or a custom header so CSP headers can be written in the nginx config).
I believe this addresses the problems identified before:
This, along with the other .html.erb
partials containing inline scripts could simply include the nonce
attribute within their script tags.
app/helpers/application_helper#theme_lookup
seems to be the method used for inserting themesā head_tags
. It could be extended to parse the html to be inserted, and add the nonce
attribute to any script tags.
This could sit behind a site preference, so sites relying on plugins which donāt update to work with nonces donāt break them.
From the previous CSP feedback, and my own grepping of places <script>
tags appear in the codebase, I canāt see what else would have to be done to make Discourse compatible with nonce-source.
Is there anything Iāve missed? Would a PR be welcome to implement this?
I havenāt yet thought through how this could be tested to ensure <script>
tags lacking a nonce
arenāt added in future.