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
| Directive | What to check | Why it matters |
|---|---|---|
| default-src | 'self' as the fallback baseline | Weak defaults leave gaps when a more specific directive is missing. |
| script-src | Inline execution, eval, and broad hosts | This is usually the highest-risk CSP area. |
| connect-src | API, analytics, and telemetry origins | Overly broad connections widen where the browser can send data. |
| frame-ancestors | Missing or permissive embed policy | Important 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/cspExpress 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
- Capture the current header Document the exact policy and the pages that rely on it.
- Use report-only first on complex apps Discover blocked resources before enforcing a stricter policy.
- Replace unsafe patterns Prefer nonces, hashes, or refactoring over permanent inline exceptions.
- 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.