Cookies This site keeps only what it needs to work. There is no analytics and no advertising on it today, and nothing here follows you to other sites. Read the privacy policy

Choose what to allow
+92 312 8299940Free Quote
Blog

Content Security Policy: Add a CSP Without Breaking Your Site

Content security policy in plain words: start strict, read the console, allow only what you use, and test with Report-Only before you go live.

By the Denwix team 6 min read

What Is a Content Security Policy?

A content security policy, or CSP, is a response header that lists where a page may load scripts, styles, fonts, images and frames from. Anything not on the list is blocked.

Its main job is to stop cross-site scripting. If an attacker manages to inject a script into your page, the browser still refuses to run it, because the script is not on the list. So a good policy turns many dangerous bugs into harmless ones.

Diagram: start strict in Report-Only, read the console, then allow exactly the hosts and hashes you use
Build the policy in three steps, so nothing breaks.

Step 1: Start Strict

Begin with the strictest useful policy. In the .htaccess file on Apache, add one line that says only files from your own site may load:

Header always set Content-Security-Policy "default-src 'self'"

Then reload the page. It still opens, but some parts may break. In our demo, a free-shipping banner added by a small inline script disappeared, and the heading font changed. That is expected, because the policy now blocks them.

Step 2: Read the Console

Open the browser's developer tools and look at the console. Every blocked file shows up there with the rule that blocked it. In our demo, the policy blocked the font stylesheet from Google Fonts and the inline script.

This list is your to-do list. Work through it one line at a time, and ask for each item: do I really need this? If not, remove it from the page instead of allowing it.

Step 3: Allow Only What You Use

Now add exact exceptions. For Google Fonts, allow styles from fonts.googleapis.com and font files from fonts.gstatic.com:

Header always set Content-Security-Policy "default-src 'self'; style-src 'self' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com"

Inline scripts: use a hash

For a small inline script, add its hash to script-src. The hash allows that exact script and nothing else. Chrome's console even prints the hash for you in the error message. Copy it into the policy:

script-src 'self' 'sha256-AbC123...='
Demo: after allowing the font hosts and the script hash, the page shows the banner and font with no console errors
With exact exceptions, the page works and the console is clean.

If the script changes often, a nonce is easier: the server adds a new random value to the policy and to each script tag on every request. Either way, the policy stays strict.

Test With Report-Only First

On a live site, never switch on a new policy cold. Instead, send it as Content-Security-Policy-Report-Only. The browser then reports every problem in the console but blocks nothing, so visitors never see a broken page.

Header always set Content-Security-Policy-Report-Only "default-src 'self'"

Browse every type of page for a few days: home, articles, checkout and forms. When the console stays clean, rename the header to the real Content-Security-Policy.

Ready Examples

Every site is different, so treat these as starting points. Then check them with the console.

A simple static site

default-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'

A site with Google Analytics

default-src 'self'; script-src 'self' https://www.googletagmanager.com; connect-src 'self' https://www.google-analytics.com; img-src 'self' https://www.google-analytics.com

Directives worth adding to every policy

object-src 'none' blocks old plugins, base-uri 'self' stops a fake base link, and frame-ancestors 'self' stops other sites from framing your pages. They rarely break anything.

How to Check Your Policy

First, check your live headers with our free HTTP Header Checker. It shows the exact policy visitors receive, and it flags missing or weak parts.

Next, open the most important pages with the console open. If you see no red CSP errors, the policy fits the site. Finally, recheck after every new plugin, widget or tracking code, because each one may need its own exception.

Common Mistakes

  • Adding 'unsafe-inline' to make the errors go away. It also lets injected scripts run, which is exactly what the policy should stop.
  • Using a wildcard such as https: in script-src, which allows scripts from any site.
  • Switching on a new policy without testing it in Report-Only first.
  • Sending two different policies from the server and a plugin; the browser applies both, so the strictest rule wins.
  • Forgetting to update the policy after adding a new service.

In short: start strict, read the console, allow exact hosts and hashes, and test in Report-Only. For every directive in detail, see the MDN guide to CSP.

Questions and Answers

What is a content security policy?

A response header that tells the browser which sources a page may load scripts, styles, fonts and other files from. Everything else is blocked.

Why does my site break after adding a CSP?

The policy blocks files that are not on its list. Open the console, read each blocked item, and allow only the ones you really need.

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

A test version of the header. The browser reports every problem but blocks nothing, so you can tune the policy safely.

Should I use unsafe-inline?

No. It allows every inline script, including injected ones. Use a hash or a nonce for the few inline scripts you need.

How do I allow an inline script?

Add its sha256 hash to script-src. Chrome's console prints the hash in the error message, so you can copy it.

What is the difference between a hash and a nonce?

A hash matches one exact script. A nonce is a random value that changes on every request and is added to the policy and the script tag.

How do I allow Google Fonts in a CSP?

Allow fonts.googleapis.com in style-src and fonts.gstatic.com in font-src.

Does a CSP help SEO?

Not directly. It protects visitors and your site, which keeps your pages safe and trusted.

Can I add a CSP in a meta tag?

Yes, with a meta http-equiv tag, but some directives, such as frame-ancestors and report options, only work in the real header.

How do I add a CSP on Nginx?

Use add_header Content-Security-Policy "..." always; in the server block, then reload Nginx.

Does WordPress work with a strict CSP?

Often yes on the front end, but many plugins add inline scripts. Test in Report-Only and add hashes or nonces where needed.

What does default-src do?

It is the fallback for every type of file that has no own directive, such as script-src or img-src.

What is frame-ancestors?

A directive that says which sites may show your page in a frame. 'self' stops other sites from framing it, which blocks clickjacking.

Can I have two CSP headers?

The browser applies both, and a file must pass every policy. That usually makes the page stricter than you planned, so keep one.

Why does the console show CSP errors from extensions?

Some browser extensions inject scripts and trigger reports. Test in a private window to see only your own site's errors.

How do I allow images from another domain?

Add that domain to img-src, for example img-src 'self' https://images.example.com.

What does object-src 'none' do?

It blocks old plugin content such as Flash. Modern sites never need it, so blocking it is safe.

Is a CSP enough to stop XSS?

It is a strong extra layer, but you still need to escape output and validate input on the server.

How do I check my CSP?

Use our free HTTP Header Checker to see the live header, then browse your main pages with the console open.

Does the SEO checker test CSP?

Yes. Our SEO Checker shows whether the header is sent and links to this guide when it is missing.

Video guide

How to Add a Content Security Policy

This brief video shows each step from start to finish. Choose your language below, and switch on captions if they help.

Check Your Security Headers Now

Enter your URL in the HTTP Header Checker to see your Content-Security-Policy and every other security header.