Basic guide to Content Security Policy with Rails
The basics of setting up CSP with your Rails app
This article will go through the basics of setting up a Content Security Policy (CSP) HTTP header for Rails apps. Your CSP defines what assets are permitted within your app, then by default everything else is disallowed. I won’t pretend to know the intricacies of CSP as I am a Rails developer and not a security expert. I am just going to outline the steps I followed to get CSP working on my Rails app.
What is a Content Security Policy?
MDN have a nice summary of what CSP is:
Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft, to site defacement, to malware distribution.
The above linked document also goes through how to set it up and what browsers it’s compatible with.
Scott Helme also has a great article all about CSP.
How do I set up a Content Security Policy with Rails?
This way of setting CSP was introduced in Rails 5.2 and it sits within config > initializers > content_security_policy.rb
.
config/initializers/content_security_policy.rb
Rails.application.config.content_security_policy do |policy|
policy.default_src :self, :https
policy.font_src :self, :https
policy.img_src :self, :https, :data, '*.s3.amazonaws.com'
policy.object_src :none
policy.script_src :self, :unsafe_inline, '*.google-analytics.com', 'player.vimeo.com', '*.cloudflare.com'
policy.style_src :self, :https, :unsafe_inline, :unsafe_eval
policy.frame_src :self, '*.youtube.com', '*.vimeo.com'
# Specify URI for violation reports
# policy.report_uri "/csp-violation-report-endpoint"
end
default_src
The fallback if the source isn’t definedfont_src
Allowed origin for fonts, the above example shows that we have the fonts within our app but you may have them from Google Fonts for example so you may require something likepolicy.font_src :self 'fonts.gstatic.com'
img_src
Allowed origin for images. We have a combination of images contained within our app and images hosted on S3object_src
We allow no embedded contentscript_src
Allowed origin for scripts i.e. Google Analyticsstyle_src
We only allow styles from external files from the same originframe_src
Allowed iframes within the app i.e. if you allow YouTube iframes etc. this should be included herereport_uri
You can set up an endpoint for violation reports
How can I view my Content Security Policy?
If you want to see your CSP header in your app open up your web inspector. I use Google Chrome so I will navigate to the Network
tab. I then click on Doc
, refresh the page and click the name of the doc and then I can see the headers on the site. My CSP will be under the header content-security-policy
.
How do I test if I have the correct Content Security Policy?
To test it out I ran a local server and clicked through pages in my app. You should see if your fonts are rendering properly. Are embeds showing? Can you see images?
When setting up your CSP for the first time on production I would recommend setting another config variable in content_security_policy.rb
:
Rails.application.config.content_security_policy_report_only = true
.
This won’t apply the CSP headers when it is first deployed instead it will show you if there are any issues with your CSP in your web inspector in your console tab. This is a great tool to let you know whether there are any issues. If you deployed without doing this you run the risk of parts of the CSP not being properly set up so it may block parts of your app which will lead to a poor experience for users and potentially unhappy clients. Once you are happy that you have set up your CSP properly, comment out or delete this line and redeploy.
How did we know we were missing a CSP?
As I say at the start of this article I’m no security expert and web development is a vast beast. Someone suggested the Security Headers website to us. Simply pop the URL you want to test in and it will let you know what security headers you’re missing.
Content Security Policy gotchas
When looking at your app you may think you know all the moving parts but if your clients have access to a CMS you may not be aware of all the sources of data within you app. Here are a few potential gotchas:
- iframes
- other media embeds i.e. Soundcloud
- third party tools