Skip to content

How to add a Content-Security-Policy

Security1 min readFixes 2 checks csp-present, csp-unsafe-inline

A CSP tells browsers which scripts, styles and frames may load, and blocks most cross-site scripting even when a plugin has a hole.

Step by step, with screenshots: Subresource Integrity for third-party scripts: help and harm →

Check your own site

Runs these 2 checks and the other 191, free, in about 45 seconds.

Or run only this check with the free Mobile-friendly test + CSP generator or the free Security headers checker.

What it is

A Content-Security-Policy (CSP) is a response header that tells the browser which sources of scripts, styles, images, frames and other content a page may use. Anything not on the list is blocked, so a script injected through a vulnerable plugin or form field cannot run.

CSP is the strongest browser-side defence against cross-site scripting, one of the injection attacks in the OWASP Top 10. getReport flags pages without any CSP, and policies whose script-src still allows 'unsafe-inline', 'unsafe-eval' or a * wildcard, since those let injected scripts run. A strong policy allows scripts by nonce or hash, and sets object-src 'none' and base-uri 'none'.

What a passing site looks like

  • Content-Security-Policy header is setwarning · −6 ptseffort M
  • Content-Security-Policy blocks inline and wildcard scriptswarning · −2 ptseffort M

1. Content-Security-Policy header is missing

Why it matters. A CSP blocks most cross-site scripting attacks by listing where scripts may load from. Without one, a single injected script can steal sessions or card data.

How to fix it.
  1. Start in report-only mode with Content-Security-Policy-Report-Only to see what would break.
  2. Move to an enforcing policy once the report is quiet; keep "unsafe-inline" out of script-src.

In a report the technical detail reads: Response headers contained neither content-security-policy nor content-security-policy-report-only.

2. Content-Security-Policy still allows inline or wildcard scripts

Why it matters. A script-src with 'unsafe-inline', 'unsafe-eval' or a * source still lets an injected script run, so the policy gives little of the protection you set it up for.

How to fix it.
  1. Move inline scripts into files and allow them by nonce or hash instead of 'unsafe-inline'.
  2. Replace * with the exact origins your scripts load from; drop 'unsafe-eval' once no library needs it.

Questions people ask

What does a Content-Security-Policy header look like?

It is one header with directives separated by semicolons, for example Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-r4nd0m'; object-src 'none'; base-uri 'none'; frame-ancestors 'self'. default-src is the fallback for content types you do not list, and each directive names the allowed sources. Build your policy from what your pages actually load.

What is Content-Security-Policy-Report-Only?

It is a header with the same syntax as CSP that blocks nothing and only reports what would have been blocked, to the browser console and to the address in its report-to or report-uri directive. Use it for a few weeks to find every script, style and frame your site needs, adjust the policy, then switch to the enforcing Content-Security-Policy header.

What does 'unsafe-inline' mean in a CSP?

It allows inline <script> blocks, event attributes such as onclick and javascript: links to run. Because injected scripts are usually inline, allowing them removes most of CSP's protection against cross-site scripting. Instead, give legitimate inline scripts a nonce that changes on every response, or a hash of their contents, and move event handlers into script files.

What is frame-ancestors in CSP?

It is the directive that decides which sites may show your page in a frame or iframe. frame-ancestors 'self' allows only your own site and 'none' allows no one, which protects against clickjacking. It replaces the older X-Frame-Options header, and it works only when sent as an HTTP header, not in a meta tag.

Filed under Security. Copy is generated from the same catalogue that scores every report, so what you read here is what the report says.