Making a Content-Security-Policy actually do something
A policy is easy to have and easy to make meaningless.
The two ways it ends up decorative
A wildcard in script-src — script-src * or script-src https: — allows every domain on the internet. Automated checkers report you as protected while an injected script from anywhere still runs.
'unsafe-inline' without a nonce. Blocking inline scripts is the main thing a CSP does against injection; with unsafe-inline, an injected <script> tag executes normally.
Rolling one out without breaking your app
Start with Content-Security-Policy-Report-Only and the policy you intend. Load your app, watch the console for violations, fix them, and only then switch to the enforcing header.
Going straight to a strict enforcing policy on a live app usually breaks something visible, and the instinct is then to delete the header entirely.
The directives people forget
base-uri 'self' — without it, an injected <base> tag redirects every relative URL on the page, form submissions included. form-action 'self' — stops an injected form posting your visitors' passwords elsewhere. frame-ancestors 'none' — the modern replacement for X-Frame-Options. object-src 'none' — closes off plugin content.
Not sure whether this applies to you?
Give us the address and we will tell you. No code, no access, no install — and every finding we have is shown in full, including on the free trial.
Check a site