CSP is this awesome security feature that allows you to choose which resources can load on your website. I talked about the setup I'm doing here https://discuss.flarum.org/d/4788-are-you-using-csp-headers-with-flarum
There are issues with Flarum: some inline javascript code is used to bootstrap the application (as well as code added by some extensions). Also (but not as bad) there seems to be some inline CSS.
Both of these situations need to be resolved by one of the following: (when using CSP headers of course)
1: Use 'unsafe-inline' rule, effectively rendering the whole CSP header useless, as it allows easy XSS
2: Use a nonce (needs to be both in the header and on the script tag)
3: Use a hash (hash allowed inline scripts and add them to the header)
(based on this article by Scott Helme, which is very well written)
Option 1 should obviously not be used ?
Option 2 needs to be included in the core and be used by all extensions that add javascript to the page
Option 3 could be done from a plugin, but it would need to run after every other plugin in order to parse the HTML output.
Then there is the other part: resources loaded from an external host by an extension. It would probably be easy to scan the list of external resources defined by $event->addAssets() in all extensions, but there is no way to know if these resources load other resources on other servers. For instance Google Fonts are included by using a stylesheet on fonts.googleapis.com, which in turn loads fonts from fonts.gstatic.com. This last part cannot be defined automatically from another extension. Same for script loaded by another script.
That's why I think the following should be included in the core:
- A way for extensions to register CSP rules
- And either:
- A way for extensions to register inline javascript or CSS that needs to be hashed
- A method to get a CSP nonce so it can be added to allowed content
The following could be added in a (default) extension:
- An option to enable CSP headers on the forum
- An option to add custom CSP rules (example: for images)
Last thing: maybe the bootstrap inline scripts could be moved to a js file as well ? Are there performance implications for this ? The document.getElementById('flarum-loading').style.display = 'block'; before the script tags should probably stay as-it, but could the "modules" part could be moved to its own file ?