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 compatable 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 defined
  • font_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 like policy.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 S3
  • object_src We allow no embedded content
  • script_src Allowed origin for scripts i.e. Google Analytics
  • style_src We only allow styles from external files from the same origin
  • frame_src Allowed iframes within the app i.e. if you allow YouTube iframes etc. this should be included here
  • report_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.

Screenshot of web inspector showing headers for tosbourn.com website

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

Recent posts View all

Ruby

Forcing a Rails database column to be not null

How you can force a table column to always have something in it with Rails

Writing Marketing

We've deleted an article's worth of unhelpful words

We've improved several pages across our site by removing words that add no value, and often detract from the article.