Guide · 3 min read

Content-Security-Policy without breaking your site

A CSP tells the browser which sources of scripts, styles and images to trust. It is your best defence against injected scripts and card skimmers, and it rewards a careful rollout.

Updated · HackGrade

1. Start in report-only mode

The browser reports violations in the console but blocks nothing.

nginx
add_header Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data: https:; script-src 'self'; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; object-src 'none'; base-uri 'self'" always;

2. Browse your site and read the console

Open DevTools → Console on your key pages (home, a product, the cart and checkout, the contact form). Every blocked source shows up there. Add the ones you trust, such as https://www.googletagmanager.com or your payment provider, to the matching directive.

3. Enforce

When the console is quiet, rename the header to Content-Security-Policy. Keep the report-only header alongside it while you test a stricter version.

.htaccess
Header always set Content-Security-Policy "default-src 'self'; img-src 'self' data: https:; script-src 'self' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline'; frame-ancestors 'self'; object-src 'none'; base-uri 'self'"

WordPress tips

  • Many themes and plugins use inline scripts. You may need 'unsafe-inline' in script-src at first. It’s weaker, but frame-ancestors, object-src and base-uri still help.
  • For a strict policy, use nonces: WordPress 5.7+ can add attributes to scripts printed with wp_print_inline_script_tag().
  • Put a strict CSP on your checkout first, where it matters most.

Useful directives

  • frame-ancestors 'self': modern replacement for X-Frame-Options.
  • upgrade-insecure-requests: auto-upgrades http:// resources to https://.
  • connect-src: limits where scripts can send data, which is useful against skimmers.

Sources

Related guides

Free · Instant · No sign-up

Find out your grade before someone else does.

Passive scan. Nothing is attacked without your permission.

Free to start. Paid plans from $12 a month, or a one-time report for $29. See pricing

This page is in English. Translations are on the way.