1 minute read

Figuring out a ‘proper’ CSP for my site was a process of elimination; a repeating cycle of whack-a-mole, adding parameters to the policy to remove error messages for my site resulted in the configuration below. There must be a more clever way!

The AWS Lambda HTTP Response Header Configuration that I ended up with is below in case it’s useful for anyone.

This scores a B from Mozilla Observatory. It loses points because of inline javascript and CSS. I’ll shoot for the A, but it will mean surgery on the code and I don’t have time to do that work right now.

Until I can get round to fixing it, unsafe-inline is enabled (which is a security vulnerability) in this policy - as well as a number of browser JavaScript Console errors messages relating to Disqus loading. It seems to work fine & seems to use some clever techniques to work despite a tight(ish) CSP. I also haven’t tested cross-browser-compatibility.

Don’t use this in a production configuration without understanding the implications. It’s not a completely safe configuration until the unsafe-inline and unsafe-eval has been removed - assuming that will be possible while continuing to use Google Analytics, Disqus, etc.

exports.handler = async (event, context) => {
const response = event.Records[0]().cf.response;
const headers = response.headers;

headers['strict-transport-security']() = [{key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubdomains; preload'}]();
headers['content-security-policy']() = [{key: 'Content-Security-Policy', value: "default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline' www.googletagmanager.com use.fontawesome.com www.google-analytics.com patrick-lynch.disqus.com _.disquscdn.com disqus.com _.doubleclick.net; object-src 'none'; style-src 'self' 'unsafe-inline' _.disquscdn.com; img-src 'self' data: www.google-analytics.com _.disquscdn.com _.disqus.com _.doubleclick.net; frame-src www.youtube-nocookie.com disqus.com; connect-src www.google-analytics.com _.doubleclick.net _.disqus.com"}]();
headers['x-content-type-options']() = [{key: 'X-Content-Type-Options', value: 'nosniff'}]();
headers['x-frame-options']() = [{key: 'X-Frame-Options', value: 'DENY'}]();
headers['x-xss-protection']() = [{key: 'X-XSS-Protection', value: '1; mode=block'}]();
headers['referrer-policy']() = [{key: 'Referrer-Policy', value: 'same-origin'}]();

return response;
};

More to follow…