From 0c6783816e0a7a8acad922296d3eb8cc454fb981 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Sat, 18 Jul 2026 16:30:31 +0200 Subject: Emit a report-only Content-Security-Policy with nonced inline scripts - dark-mode restore now travels nonced, the admin constants likewise - AUTH_TOKEN deleted in favour of the csrf meta tag - new report collector at /csp_reports --- config/initializers/content_security_policy.rb | 49 ++++++++++++++------------ 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'config/initializers/content_security_policy.rb') diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index d51d7139..1569942b 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -4,26 +4,29 @@ # See the Securing Rails Applications Guide for more information: # https://guides.rubyonrails.org/security.html#content-security-policy-header -# Rails.application.configure do -# config.content_security_policy do |policy| -# policy.default_src :self, :https -# 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 -# # Specify URI for violation reports -# # policy.report_uri "/csp-violation-report-endpoint" -# end -# -# # Generate session nonces for permitted importmap, inline scripts, and inline styles. -# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } -# config.content_security_policy_nonce_directives = %w(script-src style-src) -# -# # Automatically add `nonce` to `javascript_tag`, `javascript_include_tag`, and `stylesheet_link_tag` -# # if the corresponding directives are specified in `content_security_policy_nonce_directives`. -# # config.content_security_policy_nonce_auto = true -# -# # Report violations without enforcing the policy. -# # config.content_security_policy_report_only = true -# end +Rails.application.configure do + config.content_security_policy do |policy| + policy.default_src :self + policy.script_src :self + policy.style_src :self, :unsafe_inline + policy.img_src :self, :data + policy.font_src :self + policy.object_src :none + policy.frame_ancestors :none + policy.base_uri :self + policy.form_action :self + policy.report_uri "/csp_reports" + end + + # Per-request nonce; script-src only. style-src keeps unsafe_inline + # deliberately: TinyMCE emits img[style] in body content and the + # public layout carries style attributes -- CSS injection is a + # low-yield channel, script-src is where the protection lives. + config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) } + config.content_security_policy_nonce_directives = %w[script-src] + + # Report-only: nothing blocks. Enforcement is a later, deliberate + # flip once the reports have mapped reality (admin inline scripts, + # legacy hotlinked images in old bodies, embeds). + config.content_security_policy_report_only = true +end -- cgit v1.3