Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add in nonce support for Content-Security-Policy #1120

Open
wants to merge 4 commits into
base: guest_accounts
Choose a base branch
from

Conversation

ButteredCats
Copy link

@ButteredCats ButteredCats commented Nov 17, 2023

This adds in the ability to specify a nonce value for the scripts to use with the Content-Security-Policy header.
You can specify the nonce via the configuration file. Not replacing the default string has no impact as long as you keep script-src 'self' 'unsafe-inline'; in the CSP header

For example if you set nonceString to "mysupersecretnoncevalue" in the config file the NGINX setup would look something like this:

add_header Content-Security-Policy "default-src 'none'; script-src 'strict-dynamic' 'nonce-$request_id' 'self'; ...the rest of the Content-Security-Policy header
sub_filter_once off;
sub_filter_types *;
sub_filter mysupersecretnoncevalue $request_id;

It's currently set up on my instance. The reasing for the script-src options is that 'strict-dynamic' and 'nonce-$request_id' override 'self' in other browsers and force that only scripts who's nonce value has been replaced will be executed. Older browsers that don't understand nonces will fall back to 'self' and at least still function despite the lessened security. These values can be checked at https://csp-evaluator.withgoogle.com/

@ButteredCats ButteredCats changed the title Add in support for nonces for use with Content-Security-Policy Add in nonce support for Content-Security-Policy Nov 17, 2023
public/js/hlsPlayback.js Outdated Show resolved Hide resolved
@zedeus
Copy link
Owner

zedeus commented Nov 17, 2023

What kind of security does this add? Not sure I understand the purpose.

@ButteredCats
Copy link
Author

The reasoning behind using nonces is to block the loading of unknown scripts in the case that they're injected into the page, which is also why there can't be any inline JavaScript.

Even if a reference to an external JS file was injected to bypass the no inline scripts requirement, the attacker still wouldn't be able to guess the correct nonce value for that HTTP request (because it's regenerated every time) so the browser wouldn't run the malicious JavaScript.

On top of that (although an edge case imo) the string that the nonce is set to in the HTML page before being replaced by the proxy is meant to be secret so that even if the webserver itself was serving the file the attacker who uploaded it would need that secret string in order to have the proxy replace it with the generated nonce value for that HTTP request.

Do I think anyone is actively out there doing this to Nitter users? No. However I don't think more security is a bad thing, especially when it isn't very hard to set up.

Also as a sidenote, modern browsers will ignore the script-src directives after 'strict-dynamic' 'nonce-randomvalue' that I used in my NGINX example. The point of them is so that older clients that don't understand script-dynamic and nonce will fall back to the things after them and keep the security that they offer instead of having nothing at all.

@ButteredCats
Copy link
Author

ButteredCats commented Nov 18, 2023

I made a mistake with the CSP headers that I only just noticed. require-trusted-types-for 'script' half breaks JavaScript on Chrome but not Firefox for some reason. I thought it was working properly since I was mainly testing under Firefox, I apparently just didn't test long enough to notice Chrome wasn't fully working. My bad. Regardless, this doesn't negate the security that nonces add.

I've just removed that directive from my NGINX example but I am going to see if I can get that properly working under Chrome when that directive is added back into the CSP headers though.

Co-authored-by: Zed <zedeus@pm.me>
@ButteredCats
Copy link
Author

So it turns out Firefox and Safari don't support require-trusted-types-for, which explains why all was good in Firefox but not Chrome.

I managed to fix the infinite scrolling JS, but the hls JS file is also throwing errors despite videos playing fine. Given the size of the hls JS file I don't think it's going to be a trivial fix and so I believe it's best to just leave support require-trusted-types-for out of the CSP header.

While it would be nice to have it, it only comes into play if someone can execute malicious JavaScript on the site which the nonces aim to stop anyways.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants