six demon bag

Wind, fire, all that kind of thing!

2020-06-07

Content Security Policy for Question2Answer

The trickiest part of setting up my Q&A site (running on Question2Answer) was getting the content security policy right. I started with this basic policy:

default-src 'self';
script-src 'self';
style-src 'self';
img-src *;
object-src: 'none';
form-action: 'self';
frame-ancestors: 'self';

but quickly realized that it prevented some page elements from showing.


The immediate issue were some inline styles and scripts Question2Answer uses, so I had to add the unsafe-inline policy to make those work:

default-src 'self';
script-src 'self' 'unsafe-inline';
style-src 'self' 'unsafe-inline';
img-src *;
object-src: 'none';
form-action: 'self';
frame-ancestors: 'self';

I realize that unsafe-inline is not the most secure approach (obviously), but the alternatives would have been identifying all inline styles/scripts and then either calculating an sha256 hash for each occurrence and adding those to the policy, or patching a nonce for each occurrence into the software. Both of which would've been a major pain in the ass. No, thank you.

On top of that I needed some additional exceptions for reCAPTCHA, which I'm using for anti-spam protection. Fortunately Google has documented the required settings in their reCAPTCHA FAQ:

script-src https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/;
frame-src https://www.google.com/recaptcha/;

With those added, the captcha started working as well.

The policy is deployed by adding a header directive to the web server's site definition.

In Nginx (the web server I'm using) the directive looks like this:

add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/; style-src 'self' 'unsafe-inline'; img-src *; object-src: 'none'; form-action: 'self'; frame-src 'self' https://www.google.com/recaptcha/; frame-ancestors: 'self';";

In Apache the directive would look like this:

Header set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.google.com/recaptcha/ https://www.gstatic.com/recaptcha/; style-src 'self' 'unsafe-inline'; img-src *; object-src: 'none'; form-action: 'self'; frame-src 'self' https://www.google.com/recaptcha/; frame-ancestors: 'self';"

Posted 13:16 [permalink]