the following browser console error message is invoked many times on a given page
Refused to apply inline style because it violates the following
Content Security Policy directive: "style-src 'self' https:".
Either the 'unsafe-inline' keyword, a hash ('sha256-1eLkOKTGLdFR92ElIWA31YdS/7E3GLP3GvnXjSvRz+s='),
or a nonce ('nonce-...') is required to enable inline execution.
Note that hashes do not apply to event handlers, style attributes and
javascript: navigations unless the 'unsafe-hashes' keyword is present.
refers to issues in in initializer which is set at stock values, plus a reference to an ngrok address for local development purposes
Rails.application.configure do
config.content_security_policy do |policy|
policy.default_src :self, :https, 'https://343e-5-170-92-35.eu.ngrok.io'
policy.font_src :self, :https, :data
policy.img_src :self, :https, :data
policy.object_src :none
policy.script_src :self, :https
policy.style_src :self, :https
end
config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
config.content_security_policy_nonce_directives = %w(script-src)
end
These directives and their mechanisms are rather opaque to this user... and it feels particularly pointless when regarding inline styles, when sourced from self... adding , :unsafe_inline
to th style_src policy does remove them but I fail to understand how an inline style would be considered unsafe
if generated by self
.
The key thing to understand is that even if your application generates inline styles, browsers can't easily verify that these styles truly came from your application ("self") rather than being injected by malicious code. Here's why:
The Problem:
When a browser receives HTML with inline styles like , it has no built-in way to verify the origin of that style An XSS attack could inject malicious inline styles just as easily as your application can create legitimate ones The browser can't distinguish between them since both appear as inline attributes in the HTML
The Solution Approaches:
# Option 1: Use nonces (recommended)
config.content_security_policy do |policy|
policy.style_src :self, :https, :nonce
end
This allows inline styles that have a matching nonce attribute:
<div style="color: red" nonce="random-nonce-value">
# Option 2: Use hashes (also secure)
config.content_security_policy do |policy|
policy.style_src :self, :https, "'sha256-hash-of-style-content'"
end
# Option 3: unsafe-inline (not recommended)
config.content_security_policy do |policy|
policy.style_src :self, :https, :unsafe_inline
end
Better Practices:
Move inline styles to classes in stylesheets Use data attributes and CSS selectors instead If you must use inline styles, use nonces:
# In your application_controller.rb
before_action :set_content_security_policy_nonce
def set_content_security_policy_nonce
response.headers['Content-Security-Policy-Nonce'] = content_security_policy_nonce
end
<!-- In your view -->
<div style="color: red" nonce="<%= content_security_policy_nonce %>">
The reason :unsafe_inline works but isn't recommended is that it essentially turns off this security feature entirely. It's like saying "allow all inline styles regardless of source," which defeats the purpose of CSP. The core principle is: CSP prefers verifiable sources (like external stylesheets) or provable ownership (via nonces/hashes) over unverifiable inline code, even if that code comes from your application. This is because "self-generated" can't be cryptographically proven for inline code without additional mechanisms like nonces or hashes.