← Back to blog
2026-04-14·7 min read

Content Security Policy (CSP) Explained for Web Developers

What is Content Security Policy?

Content Security Policy (CSP) is an HTTP response header that tells browsers which resources are allowed to load on your page. It is the single most effective defense against cross-site scripting (XSS) attacks.

When a browser receives a CSP header, it enforces a whitelist. Any script, stylesheet, image, or other resource not explicitly allowed by the policy is blocked. If an attacker injects malicious JavaScript into your page, CSP prevents the browser from executing it.

Why CSP matters

XSS is the most common web vulnerability. It appears in the OWASP Top 10 every year. A successful XSS attack can steal session tokens, redirect users to phishing pages, deface your site, or exfiltrate sensitive data.

CSP does not prevent the injection itself, but it neutralises the payload. Even if an attacker finds an injection point, the browser refuses to execute unauthorized scripts.

How CSP works

You add a Content-Security-Policy header to your HTTP responses. The header contains directives that specify allowed sources for each resource type:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src *; connect-src 'self' https://api.example.com

Key directives

  • **default-src** — fallback for all resource types not explicitly listed
  • **script-src** — allowed sources for JavaScript
  • **style-src** — allowed sources for CSS
  • **img-src** — allowed sources for images
  • **connect-src** — allowed targets for fetch, XHR, and WebSocket
  • **frame-src** — allowed sources for iframes
  • **font-src** — allowed sources for web fonts
  • Source values

  • `'self'` — same origin only
  • `'none'` — block everything
  • `'unsafe-inline'` — allow inline scripts/styles (weakens CSP significantly)
  • `'unsafe-eval'` — allow eval() (avoid if possible)
  • `'nonce-abc123'` — allow specific inline scripts with a matching nonce attribute
  • `https://cdn.example.com` — allow a specific external origin
  • Building your first CSP

    Step 1: Start with report-only mode

    Use Content-Security-Policy-Report-Only instead of Content-Security-Policy. This logs violations without blocking anything, so you can see what would break.

    Step 2: Start strict, then loosen

    Begin with `default-src 'none'` and add only what your site actually needs. Review the violation reports and add legitimate sources one at a time.

    Step 3: Eliminate unsafe-inline

    Replace inline scripts with external files or nonce-based scripts. This is the most important step for real XSS protection.

    Step 4: Switch to enforcement

    Once your report-only policy runs clean for a week, switch the header to Content-Security-Policy.

    Common mistakes

  • Using `unsafe-inline` and `unsafe-eval` everywhere (defeats the purpose of CSP)
  • Setting CSP once and never updating it (new third-party scripts will break)
  • Overly broad wildcards like `*.googleapis.com` (allows more than intended)
  • Forgetting connect-src for API calls (fetch requests fail silently)
  • CSP and single-page applications

    Frameworks like React, Next.js, and Vue often use inline scripts for hydration. Use nonce-based CSP: generate a unique nonce per request, add it to your CSP header, and inject it into your script tags.

    [Check your CSP configuration now](/tools/csp-checker)

    Ready to check your domain?

    Run all 18 security checks in 2 minutes. Free, no signup required.

    Free CSP Checker