Critical

Content-Security-Policy

Tells the browser exactly which sources are allowed to load scripts, styles, images, and other resources on your pages.

What it does

Content-Security-Policy (CSP) is an allow-list, enforced by the browser, for where page content is permitted to come from. If an attacker manages to inject a <script> tag into your page, through a comment field, a vulnerable dependency, a compromised ad network, a well-configured CSP simply refuses to execute it, because the script's source isn't on the list.

Why it matters

CSP is the single most effective defence against cross-site scripting (XSS). Even a small oversight elsewhere in your stack, an unescaped template variable, a permissive third-party widget, becomes far less dangerous when the browser itself won't run unauthorised code.

A missing CSP doesn't create a vulnerability by itself, but it removes a safety net that would otherwise contain the damage from other bugs.

Getting started

A full lockdown policy can break legitimate scripts, fonts, and embeds if rolled out carelessly, so most teams start in report-only mode:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

This logs violations without blocking anything, so you can see what your policy would break before enforcing it. Once the reports are clean, switch to the enforcing header:

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; object-src 'none'

Key directives

  • default-src: the fallback allow-list for any resource type without its own directive.
  • script-src: where JavaScript may load from. Avoid 'unsafe-inline' and 'unsafe-eval' here if at all possible; they largely defeat the purpose of CSP.
  • object-src 'none': blocks Flash/plugin content almost universally recommended to disable outright.
  • frame-ancestors: the modern, CSP-native replacement for X-Frame-Options.

Because every application's third-party scripts and embeds differ, there's no one-size-fits-all policy: treat the example above as a starting point, not a copy-paste answer.