HeaderAudit

Content-Security-Policy

Controls which sources the browser will load and execute content from. The single most effective defence against cross-site scripting.

Recommended value

Content-Security-Policy: default-src 'self'; script-src 'nonce-{random}' 'strict-dynamic'; object-src 'none'; base-uri 'self'

What it does

CSP turns the browser into an enforcement point. Without it, any HTML injection becomes script execution, which is what turns a small bug into account takeover.

The mistake almost everyone makes is treating CSP as a checkbox. A policy can be present, three lines long, and enforce nothing at all — because 'unsafe-inline' permits exactly the injected inline script CSP exists to stop.

Two rules decide whether a policy does anything, and both are counter-intuitive:

A nonce or hash disables 'unsafe-inline'. Browsers that understand nonces ignore 'unsafe-inline' entirely when one is present. So a policy containing both is not broken — that is the standard pattern for supporting old browsers, and a scanner flagging it as a vulnerability is wrong.

'strict-dynamic' disables the host allowlist. When it is set, the carefully curated list of CDN domains is ignored. Trust propagates from the nonce to scripts those scripts load. This is a feature: allowlists are widely bypassable, because one JSONP endpoint or one vulnerable library on any allowlisted host defeats the whole policy.

Sites sending this header

Found while scanning 188 well-known sites on 2026-08-04:

Check a site