Security · Checked once per domain
Content Security Policy (CSP) headersWhat it checks and how to fix it
What it checks
Fetches the homepage and reads the Content-Security-Policy header. No CSP at all fails. A policy sent only as Content-Security-Policy-Report-Only, or one containing unsafe-inline, unsafe-eval or a bare * source, gets a warning. An enforced policy without those passes.
Why it matters
A Content Security Policy tells the browser which scripts, styles and frames a page may load. It is the main defence in depth against cross-site scripting: if an attacker manages to inject markup, a strict CSP stops the injected script from running or sending data out. unsafe-inline and unsafe-eval switch most of that protection off, and a report-only policy only reports.
How to fix it
Start from a restrictive policy, ship it as Content-Security-Policy-Report-Only while you fix what it reports, then switch to the enforcing header. Use nonces or hashes for inline scripts instead of 'unsafe-inline'.
A reasonable starting policy:
default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'self'; base-uri 'self'; form-action 'self'; object-src 'none'
nginx
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'" always;
Apache
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"
Cloudflare: Rules → Transform Rules → Modify Response Header → set Content-Security-Policy for your hostname.
Rails (config/initializers/content_security_policy.rb)
Rails.application.configure do
config.content_security_policy do |policy|
policy.default_src :self
policy.script_src :self
policy.style_src :self
policy.img_src :self, :data, :https
policy.object_src :none
policy.base_uri :self
policy.frame_ancestors :self
end
# Nonces let inline <script> tags written with javascript_tag / nonce: true run
config.content_security_policy_nonce_generator = ->(request) { SecureRandom.base64(16) }
config.content_security_policy_nonce_directives = %w[script-src]
end