DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Mike Doyle
Mike Doyle

Posted on

Rails 7 & CSP - How to add a nonce to an inline <style> tag (if you must)

I've been trying to get the Content Security Policy working in a new Rails 7 application but I have a <style> element in the document<head> that is causing problems when the CSP is enabled.

I don't want to add unsafe_inline to my CSP so the only other option is to use a nonce!

Unfortunately I need the styles to be "inline" because they are used to customize some CSS variables based on the logged in user's preferences and an inline style element with some ERB seemed like the quickest way to accomplish that

Here's how I ultimately got it working:

content_tag(:style, nonce: content_security_policy_nonce) do
  ':root { --css-var: value; }'
end
Enter fullscreen mode Exit fullscreen mode

The import part is the content_security_policy_nonce method (which just calls request.content_security_policy_nonce) will render the nonce in your ERB after the following two requirements are met

  • You have <%= csp_meta_tag %> in your layout
  • You have something along these lines in your content security policy configuration
config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) }
config.content_security_policy_nonce_directives = %w(script-src style-src)
Enter fullscreen mode Exit fullscreen mode

See https://edgeguides.rubyonrails.org/security.html#adding-a-nonce for more info on configuring the nonce

The most important thing is to add style-src to the nonce directives. By default a new Rails project will only include script-src.

Rails does provide an easy way to do this with <script> tags but not with <style> tags - so here we are.

<%= javascript_tag nonce: true do -%>
  alert('Hello, World!');
<% end -%>
Enter fullscreen mode Exit fullscreen mode

I know its not good practice to have inline styles like this but this could be really helpful while adding CSP to a legacy app or when you really need to have the styles inline/in the head.

Top comments (0)

🌚 Life is too short to browse without dark mode