As I’ve been working on the website for Eventbot, I’ve been playing around with the site’s Content Security Policy (CSP). Now, before you tear me to shreds for the incendary title, let me get this out of the way: I like Content Security Policies. It’s a damned good idea, easy to implement, and well documented. If you already know all about CSPs you can skip the next paragraph.
Anyways, it’s a great idea, but when it comes to working with 3rd party libraries, it’s a huge pain in the ass for a number reasons:
Minimal documentation for what to whitelist.
There’s rarely any documentation about what urls and permissions to grant for third party libraries like Google Analytics, Mixpanel, or Segment. Sure, report-only allows devs to fix errors as they appear, but it’s annoying and it very well may be incomplete. Some urls may only be triggered in rare conditions, or, worse, the script could change without warning.
Strange programming choices
I got this CSP error from embedding a Zendesk script:
violated-directive: script-src script-sample: 'call to eval() or related function blocked by CSP', source-file: 'https://assets.zendesk.com/embeddable_framework/main.js',
Zendesk uses a script that has an eval. Hilariously, in the minified script, you’ll find
return eval("false"). Maybe this is a weird result from minification? Anyways, to deal with this, I have nothing but blah options: Block the eval, Allow eval globally, or use some other help desk service.
Use of Data and Blob
Here’s a report from a script using a data url:
blocked-uri: data, violated-directive: font-src, source-file: https://v2.zopim.com
Interestingly, I cannot whitelist a particular data url e.g.
data:abcd1234. It’s either all or nothing. The same problem goes for “blob” urls as well. I think this could be an interesting place where CSP could improve.
Segment is an interesting service that allows a user to embed one script, and turn on or off various services (like Zendesk, Google Analytics, etc). It’s handy for all sorts of reasons, but it’s a nightmare if the webpage has a CSP. Someone can just flip on Mixpanel, but if its urls are never added to the CSP, well, it’s going to be blocked. I don’t think there’s much Segment can do here, but improved documentation, as I mentioned above, would be a good start.
No subdomain wildcards (EDITED)
Here’s some very similar looking reports. Note the subdomains:
blocked-uri: wss://us34.zopim.com, violated-directive: connect-src... blocked-uri: wss://us22.zopim.com, violated-directive: connect-src... blocked-uri: wss://us24.zopim.com, violated-directive: connect-src...
I have no idea what Zopim’s rationale for having multiple different subdomains, but unfortunately, CSPs do not allow subdomain wildcards. It’s not a big deal if there’s a few, but in this case there’s a ton. Bummer. Anyways, this is another area I think CSP could potentially improve.
EDIT 2/22/18: It turns out CSPs do allow for subdomain wildcards. I don’t know where I got my info, but adding
https://*.zopim.com to a CSP totally works. Sorry about that. Thanks to the friendly folks at Zendesk for pointing this out.
Alerts from extensions
blocked-uri: data document-uri: about:blank violated-directive: font-src blocked-uri: https://translate.googleapis.com document-uri: https://geteventbot.com/
The first report above is from an extension. The second is because someone used Chrome’s handy translation feature! It’s not a huge deal, but it raises some confusing questions. Am I breaking someone’s extensions. Should I? I wouldn’t think I would want to. Should browsers even send these kind of CSP reports?
Anyways, I hope this doesn’t dissuade you from using a CSP. You should, and you should test your headers on securityheaders.io.
Finally, if you’re writing a library you intend others to consume as a 3rd party, I have some suggestions I hope you keep in mind:
- Publish an example CSP that would allow your script to work that doesn’t include any “unsafe” items
- Keep this example CSP compact. If you have 50 subdomains, please rethink your strategy
- Avoid all-or-nothing properties, like data, eval, and blob if possible
Anything else that should be on this list? Did I get something wrong? Let me know!