Content-Security-Policy
This article is a stub. You can help the IndieWeb wiki by expanding it.
Content-Security-Policy (abbreviated CSP) is an HTTP directive that a site can use to restrict what external resources are retrieved by a browser, to mitigate some XSS and injection attacks.
Why
AT&T hotspot ad injection into http sites: http://webpolicy.org/2015/08/25/att-hotspots-now-with-advertising-injection/
How to
Send CSP header
Configure your webserver to send a
Content-Security-Policy
HTTP header (e.g. for Apache, update your .htaccess) according to the policy you prefer (see Examples section below for options to consider for your site.
Test your CSP
Check that your server is sending the right CSP:
- Go http://www.whatsmyip.org/http-headers/
- Enter your domain (or a post permalink) into the big white text box
- click "Get Headers"
- scroll down to "HTTP Response Headers"
- you should see an entry for "Content-Security-Policy" in the left column, and on its row in the right column, it should show exactly what you configured your server to send.
Then load your site/permalinks in whatever browsers you can run, and check their View/Tools/Developer (Web Console, Show Error Console, Developer Tools) for errors, in particular for anything being blocked that you wanted to load.
Examples
Only Resources From Same Domain
Only allow external resources from the precise same domain, no subdomains:
Content-Security-Policy: default-src 'self'
Include subdomains:
Content-Security-Policy: default-src 'self' *.example.com
Where example.com is your trusted top level personal domain.
Allow Only Media From Anywhere
Allow images/audio/video embeds from anywhere, but scripts, style sheets, iframes etc. only from same domain:
Content-Security-Policy: default-src 'self'; img-src *; media-src *
- Why
img-src *
- Embedding images from external domains is a fairly common practice, e.g. icons of people in reply-contexts, comments, or photos hosted on other domains (e.g. silos), etc. Alternatively if you proxy all your images through a subdomain on your site (i.e. to uplevel them to https), then you could restrict img-src to that subdomain (with https).
- Why
media-src *
- Also if you autolink your notes, e.g. with the CASSIS
auto_link()
function, then you're likely also auto-embedding as part of that and thus turning any common audio file extension link into an<audio>
and similarly with video file extension links and<video>
. Since those audio/video file links can be from any domain, themedia-src *
makes sense.
Allow Anywhere Media Whitelist Iframes
Allow images/audio/video embeds from anywhere, iframes from an https whitelist, and scripts, style sheets only from same domain:
Content-Security-Policy: default-src 'self'; img-src *; media-src *; child-src https://player.vimeo.com https://www.youtube.com
- Why
child-src https://player.vimeo.com https://www.youtube.com
- Again if you use an autolink function that auto-embeds, then it's likely turning every YouTube and Vimeo link into an iframe to embed players for those videos. That
child-src
directive in the example explicitly allows loading of external iframes only over https only from those specific domains (whitelist).
IndieWeb Examples:
- Tantek Çelik uses this, with
frame-src
(previous version of child-src) for backcompat, and a few more directives. See details in IndieWeb Examples: Tantek.
IndieWeb Examples
Tantek
Tantek Çelik on tantek.com since 2015-08-28 has used the following CSP (updated 2016-108) on his home page and post permalinks:
Content-Security-Policy: default-src 'self'; img-src *; media-src *; script-src 'self' 'unsafe-inline' https://platform.twitter.com; style-src 'self' 'unsafe-inline'; frame-src *; child-src *;
Based on the Allow Anywhere Media Whitelist Iframes example above, with the following additions for the following reasons:
script-src 'self' 'unsafe-inline'
- because I still have some inline scripts that I didn’t want to take the time to fix before, but now have motivation to do so.style-src 'self' 'unsafe-inline'
- because I still have some inline style sheets and style attributes that I didn’t want to take the time to fix before, but now have motivation to do so.frame-src
- for backcompat with Safari 8.0.7 (and before?) which is latest version on OSX 10.10.4, and Microsoft Edge (tested as of 2015-08-28 Microsoft Edge build).child-src *;
(as of 2016-108) necessary to support indie-config. Previously:child-src platform.twitter.com
- to also allow Twitter tweet buttons as noted above.
Note:child-src platform.twitter.com
instead ofchild-src https://platform.twitter.com
(which would be better) because the current platform.twitter.com/widgets.js, even if referenced via https, has one spot where it does an iframe embed that is parent page protocol relative, and thus ends up embedding an http iframe. To be able to use only the child-src https, I need to either:- Get Twitter to fix platform.twitter.com/widgets.js to always embed its iframe with https, OR
- Switch my site to using https so the protocol relative iframe src will also be https, OR
- Drop the "Tweet" button from my article posts (in which case I could drop the
platform.twitter.com
from thechild-src
andframe-src
completely.)
Shane Becker
Shane Becker on veganstraightedge.com using Dark Matter since 2016-02-24 has used the following CSP on his website
Content-Security-Policy: default-src 'self' http:; child-src *; frame-src *; img-src * data:; media-src *; script-src 'self' platform.instagram.com ; style-src 'self' 'unsafe-inline'
Based on the Allow Anywhere Media Whitelist Iframes and Tantek Çelik's examples above, with the following additions for the following reasons:
default-src 'self' http:
- My software (Dark Matter) addshttp:
orhttps:
to match whatever the site uses (based on a setting that is user changeable to match their site's scheme)child-src *
- Both of these are set to*
mainly because I couldn't get this work with a list. I plan change this to an explicit list when I figure out what my code's problem is.frame-src *
- Both of these are set to*
mainly because I couldn't get this work with a list. I plan change this to an explicit list when I figure out what my code's problem is.img-src * data:
- I includedata:
because I'm using some SVG from a data://url in addition to SVG img[src=url.svg]script-src 'self' platform.instagram.com
- I don't include'unsafe-inline'
because I don't already have any inline script blocks that I need to support. And I don't want to support them going forward. I don't includehttps://platform.twitter.com
because I don't have Twitter buttons on my site. I also addedplatform.instagram.com
because I use Instagram's embed code.- I'll add more domains to this whitelist for auto-embeds in Notes.
- I'll eventually remove instagram in particular by building an auto-embed that doesn't use Instagram's JS/iframe.
style-src 'self' 'unsafe-inline'
- I also include'unsafe-inline'
because post specific styles are served up intostyle
tags. And I don't see a meaningful security hole by allowing CSS in style tags.
Bridgy
Bridgy has used the following CSP since 2016:
Content-Security-Policy: script-src https: localhost:8080 my.dev.com:8080 'unsafe-inline'; frame-ancestors 'self'; report-uri /csp-report;
... add your site too! ...
Add your site, when you started using a CSP, and preferably copy/paste it here inline and explain any changes from the common practices in the Examples section.
FAQ
Why bother if attacker can hack CSP too
Q: On an HTTP (not HTTPS) connection, an attacker can theoretically either strip your CSP header, modify it (to allow their junk), or replace it entirely with one of their own. Why bother adding a CSP since it too can be attacked?
A: In short, Defense in Depth.
Longer:
Just because an attacker is willing to use one mechanism, it doesn’t mean they are willing (or even necessarily capable - even if you think it is "obvious") to use another mechanism.
In the case of ATT wifi hotspots injecting ads, it's one thing to just add ads to the page, but it's quite different in quality and nature to remove/change HTTP headers, especially one with security in its name, hence they are unlikely to do so. That being the original use-case we were solving for, we can consider it solved.
And even if an attacker is willing to workaround multiple mechanisms, they are having to spend more time doing so, which in some cases may be enough to thwart an attack, especially if time/timing is an issue.
For more on the general concept see: Wikipedia: Defence in depth.
Resources
- W3C Content Security Policy Editor’s Draft
- 2012-06-15 (updated 2015-05-08) Mike West An Introduction to Content Security Policy
- https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Introducing_Content_Security_Policy
- https://developer.mozilla.org/en-US/docs/Web/Security/CSP/Using_Content_Security_Policy
- http://githubengineering.com/githubs-csp-journey/
See Also
- HTTPS
- CORS
- sandbox
- Laboratory, a Firefox add-on that allows you to record / change / test CSP on live websites.
- https://medium.com/@david.gilbertson/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5
- Implementing Content Security Policy by Mozilla Hacks covers the basics of implementing CSP, based on what they learned from implementing it on addons.mozilla.org