Browser Policy 14 min read

CSP Checker Guide

Use this guide to understand what the CSP Checker is validating, how to replace unsafe patterns, and how to promote a stricter policy without breaking production journeys.

Overview

A useful CSP review separates cosmetic policy changes from directives that materially reduce script injection, clickjacking, and third-party script risk.

What deserves attention first

  • script-src: Review unsafe-inline, unsafe-eval, and broad third-party allowlists first.
  • frame-ancestors: Protect admin, login, and billing routes from embedding.
  • report-only: Use it to stage stricter changes safely before enforcement.

Directives and Risk Areas to Review

DirectiveWhat to checkWhy it matters
default-src'self' as the fallback baselineWeak defaults leave gaps when a more specific directive is missing.
script-srcInline execution, eval, and broad hostsThis is usually the highest-risk CSP area.
connect-srcAPI, analytics, and telemetry originsOverly broad connections widen where the browser can send data.
frame-ancestorsMissing or permissive embed policyImportant for admin, login, and payment-sensitive views.

Practical Policy Examples

Report-only rollout header
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' https://www.googletagmanager.com 'nonce-random123'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https://api.example.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; report-uri https://reports.example.com/csp
Express with Helmet and nonces
const helmet = require('helmet');

app.use(helmet.contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", "'nonce-random123'"],
    styleSrc: ["'self'", 'https://fonts.googleapis.com'],
    imgSrc: ["'self'", 'data:', 'https:'],
    frameAncestors: ["'none'"],
    baseUri: ["'self'"],
    formAction: ["'self'"]
  }
}));

Recommended Remediation Flow

  1. Capture the current header Document the exact policy and the pages that rely on it.
  2. Use report-only first on complex apps Discover blocked resources before enforcing a stricter policy.
  3. Replace unsafe patterns Prefer nonces, hashes, or refactoring over permanent inline exceptions.
  4. Retest critical journeys Validate login, checkout, analytics, and admin flows after the change.

Troubleshooting Common Issues

Analytics or tag-manager scripts stop loading

Usually the policy is missing a required script host or the app still relies on inline bootstrap code.

  • Confirm the blocked host from browser console or report-only output.
  • Move inline bootstrap logic to nonce-backed scripts.
  • Avoid restoring broad wildcard hosts just to get one integration working.
Fonts, icons, or styles disappear after enforcement

This is often caused by style-src or font-src being too narrow for your actual asset sources.

  • Review style-src and font-src together.
  • Check whether the build rewrites asset URLs differently in production.
  • Consider self-hosting assets if third-party hosts are hard to manage.

Validation Checklist

Post-fix validation

  • Confirm the final response contains one authoritative CSP header.
  • Review browser console or report-only telemetry for blocked resources after deployment.
  • Retest high-value pages such as login, checkout, dashboards, and embeds.
  • Run the CSP Checker again and compare the remaining findings to the intended policy.

FAQ

Should every site remove unsafe-inline immediately?

Not always. Older apps often need a staged report-only rollout first.

  • Remove it quickly where refactoring is simple.
  • Use nonces or hashes when inline execution still exists.
  • Do not keep unsafe-inline permanently just because the first removal attempt broke analytics.
Is CSP enough to stop XSS on its own?

No. CSP reduces exploitability, but it does not replace output encoding or safer templates.

  • Keep input handling and template safety in scope.
  • Review third-party script usage separately from CSP syntax.
  • Use wider scanning when you need broader application coverage.