How Content-Security-Policy (CSP) Works: Complete Guide

CSP is the single most effective browser-enforced defense against cross-site scripting. Here's how the directive syntax works and how to roll one out safely.

📅 Published July 2026· ⏳ 10 min read· ✍️ ToolsNovaHub Editorial Team
Content-Security-Policy (CSP) is a response header that tells the browser exactly which sources are allowed to supply scripts, styles, images, fonts, frames, and other resources for a page. Anything not on the allow-list simply won't execute or load — turning an entire class of injection attacks from a live exploit into a browser console error.

The Core Idea

By default, a browser will execute any script tag present in a page's HTML, regardless of where it came from — including one an attacker managed to inject via an unescaped form field or vulnerable third-party widget. CSP flips this to a default-deny model: only sources you've explicitly allow-listed can supply content, and inline scripts are blocked by default unless specifically permitted.

Key CSP Directives

DirectiveControls
default-srcFallback source list for any directive not explicitly set
script-srcWhere JavaScript may be loaded from
style-srcWhere CSS may be loaded from
img-srcWhere images may be loaded from
connect-srcAllowed targets for fetch/XHR/WebSocket calls
frame-ancestorsWhich sites may embed this page in an iframe (replaces X-Frame-Options)
object-srcControls plugins like Flash/Java applets — usually set to 'none'
base-uriRestricts what <base> tags can set, preventing base-tag hijacking

Writing a Real Policy

A reasonably strict but workable starting policy for a typical site using a CDN and Google Analytics:

Content-Security-Policy: default-src 'self'; script-src 'self' https://www.googletagmanager.com; style-src 'self' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https://www.google-analytics.com; frame-ancestors 'self'; object-src 'none'; base-uri 'self'

Notice everything is scoped to 'self' by default, with specific third-party origins added only where actually needed — the opposite of a wildcard * approach, which defeats most of the protection.

Report-Only Mode: Test Before You Enforce

Deploying a strict CSP directly to production risks silently breaking functionality that depends on a resource you didn't account for. Use the Content-Security-Policy-Report-Only header instead first — the browser evaluates the policy and logs violations to the console (and optionally to a report-uri endpoint) without actually blocking anything. Once you've reviewed violation reports and confirmed no legitimate functionality is affected, switch to the enforcing header.

Common Pitfalls

  • Using 'unsafe-inline': This defeats most of CSP's XSS protection since it allows any inline script to run, including an injected one. Prefer nonces or hashes instead (see below).
  • Forgetting third-party widgets: Chat widgets, analytics, ad scripts, and embedded maps often load additional resources dynamically from domains not in your original allow-list.
  • Not testing report-only first: Jumping straight to an enforcing policy on a complex site frequently breaks something that only surfaces after deployment.
  • Overly broad wildcards: A directive like script-src * technically satisfies "having a CSP" while providing almost no actual protection.

Nonces & Hashes for Inline Scripts

If you genuinely need inline scripts, CSP supports cryptographic nonces (a random value generated fresh per page load and matched in both the header and the script tag) or hashes (a SHA hash of the exact script content). Both let specific, known-good inline scripts execute while still blocking any attacker-injected ones, since an attacker can't predict the nonce or produce a script matching a pre-approved hash.

Example nonce usage: script-src 'nonce-r4nd0mVal123' paired with <script nonce="r4nd0mVal123"> in the HTML.

FAQs

Content-Security-Policy — an HTTP response header that allow-lists which sources may supply scripts, styles, images, and other resources for a page.
Cross-site scripting (XSS) — even if an attacker manages to inject a script tag into a page, the browser refuses to execute it unless its source is on the CSP allow-list.
A testing mode where the browser evaluates the policy and logs violations without actually blocking anything, letting you find breakage before enforcing the policy in production.
It permits any inline script to execute, including ones an attacker injects, which defeats most of CSP's core XSS protection. Nonces or hashes are the recommended alternative for legitimate inline scripts.
A random, single-use value generated per page load, included both in the CSP header and matching script tags, allowing specific known-good inline scripts to run while blocking attacker-injected ones.
No. CSP is a browser-side defense against resource-loading and script-execution attacks like XSS — it has no effect on server-side vulnerabilities like SQL injection.
Yes — an overly strict policy that doesn't account for all legitimate resource sources (analytics, widgets, CDNs) can silently block functionality, which is why report-only testing first is strongly recommended.
default-src is the fallback allow-list applied to any directive not explicitly specified. script-src specifically controls JavaScript sources and, when set, overrides default-src for scripts.
Nonces are easier for dynamically rendered pages since the value can be generated fresh each request. Hashes work well for genuinely static inline scripts that never change, since the hash must exactly match the script content.
CSP's frame-ancestors directive is the modern replacement offering finer-grained control over which origins may embed your page, but many sites keep both for broader browser compatibility.
Deploy in report-only mode first and check browser developer console violation logs, or set up a report-uri endpoint to collect violation reports centrally.
Yes, but each ad network's specific domains need to be explicitly added to the relevant directives — ad networks often load resources from many different sub-domains, requiring careful allow-listing.
It falls back to whatever default-src specifies. If default-src itself is restrictive and the resource type isn't separately allow-listed, it will be blocked.
All modern browsers support CSP, though support for specific newer directives can vary — always test across your target browser matrix rather than assuming universal support for every directive.
Start with default-src 'self' plus explicit allow-listing for every third-party resource you actually use, test thoroughly in report-only mode, then enforce — rather than starting broad and trying to tighten later.
Reviewed by: ToolsNovaHub Editorial Team📅 Last updated: July 2026📜 Sourced from: official RFC / vendor documentation

ToolsNovaHub tools are built and independently maintained with a focus on accurate, no-signup network and security utilities. Spotted an error? Let us know.

🎓
Expert Tip
A single scan from How Content-Security-Policy (CSP) Works: Complete Guide is a snapshot — security posture drifts as certificates near expiry or headers get overwritten by a new deploy, so schedule periodic re-checks.
ToolsNovaHub Pro Tip
Combine How Content-Security-Policy (CSP) Works: Complete Guide with our Website Security Scanner for one combined view covering TLS, headers, and email authentication together.
⚠️
Common Beginner Mistake
Assuming a perfect score from How Content-Security-Policy (CSP) Works: Complete Guide means the site is fully secure. It checks configuration, not application-layer bugs like SQL injection — pair it with a manual code review.

📋 Related Tools & Guides Comparison

ResourceTypeLink
Blacklist CheckSecurityOpen Tool →
SSL Certificate CheckerSecurityOpen Tool →
Security Headers CheckerSecurityOpen Tool →
Common Website Vulnerabilities Checklist: What to Check & FixGuideRead Guide →
How to Fix an Expired SSL Certificate (Step-by-Step Guide)GuideRead Guide →
Explore All ToolsNovaHub Tools
🏠 Go to Homepage

🔗 More Guides