Two tools help with Content-Security-Policy (CSP). The CSP Evaluator grades an existing policy and explains each finding. The CSP Generator builds a new policy and grades it as you go. Both use the same rules.
Evaluate a policy
You can give the evaluator a policy in two ways:
- Paste it. The policy is evaluated in your browser and nothing is sent to Vigilbase.
- Fetch it from a URL. Vigilbase runs the Security headers scan on the URL and evaluates the CSP it returns. You can then email yourself the Security Headers report.
When a site sends both an enforced policy and a Content-Security-Policy-Report-Only policy, only the enforced one is graded; the Report-Only policy is listed for reference. A Report-Only policy on its own is graded as if it were enforced, with a note that it blocks nothing.
How the evaluator grades
The score starts at 100 and each finding deducts points by severity:
| Severity | Points |
|---|---|
| Critical | 50 |
| High | 25 |
| Medium | 10 |
| Low | 5 |
| Info | 0 |
| Grade | Score |
|---|---|
| A+ | 95-100 |
| A | 85-94 |
| B | 70-84 |
| C | 55-69 |
| D | 40-54 |
| F | 0-39 |
A+ and A are Secure, B and C are Warnings, and D and F are Vulnerable.
Main findings
| Finding | Severity | Fix |
|---|---|---|
| Scripts are not restricted | Critical | Add a script-src directive, ideally nonce- or hash-based with 'strict-dynamic'. |
| 'unsafe-inline' allows inline scripts | High | Remove 'unsafe-inline' and allow your own inline scripts with a per-response nonce or their hashes. |
| Inline event handlers are allowed | High | Move event handlers into script files, or allow specific handlers with 'unsafe-hashes' and their hashes. |
| Scripts can load from any host | High | Replace wildcards and schemes with a nonce or hashes plus 'strict-dynamic'. |
| 'unsafe-eval' allows eval() | Medium | Remove 'unsafe-eval' and refactor code that builds scripts from strings. For WebAssembly, 'wasm-unsafe-eval' is enough. |
| Scripts allowed over plain HTTP | Medium | Load scripts over HTTPS only. |
| Scripts rely on a host allowlist | Medium | Move to a nonce- or hash-based policy with 'strict-dynamic'. |
| object-src is not 'none' | Low | Set object-src 'none' unless your pages embed plugin content. |
| base-uri is missing | Medium | Add base-uri 'none', or base-uri 'self' if your pages use a <base> tag. |
| frame-ancestors is missing | Low | Set frame-ancestors 'none' or 'self'. |
| Directive ignored in a meta tag | Medium | Send the directive in the Content-Security-Policy response header. |
Informational findings, such as Report-only policy or No violation reporting, explain the policy without changing the score.
Build a policy
The generator runs entirely in your browser.
Choose how scripts are trusted. Nonce with 'strict-dynamic' (recommended) suits pages generated per request. Hashes with 'strict-dynamic' suits static pages whose inline scripts never change; paste each script to get its hash. Host allowlist is the weakest option.
Add the hosts your pages need. Fill in style, image, font, connection and frame hosts. With
'strict-dynamic', scripts that a trusted script loads need no host entry.Set the directives with no fallback. Choose base-uri, frame-ancestors and form-action, and keep Block plugins (object-src 'none') on.
Start in Report-Only. Turn on Report only and add a Report URL, then fix what the reports show.
Copy the policy. Copy the header or the Nginx, Apache or meta tag snippet. Replace
{RANDOM}with a new nonce on every response.
A meta tag cannot carry frame-ancestors, report-uri, report-to or sandbox, and cannot deliver a Report-Only policy, so send the policy as a response header where you can. On Cloudflare, a response header transform rule can set a hash- or allowlist-based header for a zone; a nonce has to come from your application.
The generator has no stored run, so it cannot email a report. To check the deployed policy, run Website Security or the evaluator's URL mode.