How HTTP Works

Tools

CSP Evaluator & Builder

Paste a Content-Security-Policy header, a bare policy or a <meta> tag and get a grade with specific findings. Or build a strict policy and copy it as a header for nginx, Express or Cloudflare. Everything runs in your browser.

Try

Runs in your browser. Nothing is sent anywhere.

Result

Score 0 / 100

3 High5 Medium4 Low2 Note

The grade is a heuristic: high findings cap it at D. It checks the policy text only, not whether your site works under it.

Findings

  • Highscript-src

    'unsafe-inline' in script-src without nonce or hash

    Inline <script> blocks and event-handler attributes are allowed, which is exactly what an XSS payload uses. This effectively disables CSP script protection.

    Fix: Add a per-response nonce to your script tags and use script-src 'nonce-…' 'strict-dynamic'; or hash static inline scripts.

    Read more in the CSP reference
  • Highscript-src

    data: in script-src

    An attacker who can inject a script tag can use <script src="data:text/javascript,..."> to run arbitrary code.

    Fix: Remove data: from script sources.

  • Highdefault-src

    default-src is not 'none'

    Plugin content from any host can be embedded, which has been a way to execute script despite a strict script-src.

    Fix: Add object-src 'none'.

  • Mediumscript-src

    'unsafe-eval' in script-src

    Allows eval(), new Function() and string-form setTimeout. If an attacker controls any string that reaches those sinks, they get script execution. Some frameworks and bundlers need it in dev only.

    Fix: Remove it in production. For WebAssembly only, use the narrower 'wasm-unsafe-eval'.

  • Mediumscript-src

    https://ajax.googleapis.com in script-src is a risky allowlist entry

    ajax.googleapis.com hosts old AngularJS builds, which can be abused as a script gadget when the page has an injection point; other *.googleapis.com endpoints have served JSONP callbacks. Allowlisting a broad host like this has been part of published CSP bypasses, so treat it as a risk, not as proof that the page is exploitable.

    Fix: Prefer nonce or hash with 'strict-dynamic', or pin the exact file with a hash or SRI.

  • Mediumscript-src

    https://cdnjs.cloudflare.com in script-src is a risky allowlist entry

    cdnjs hosts many library versions, including AngularJS and other libraries with known script gadgets. Allowlisting the whole host makes those usable by an attacker. Allowlisting a broad host like this has been part of published CSP bypasses, so treat it as a risk, not as proof that the page is exploitable.

    Fix: Prefer nonce or hash with 'strict-dynamic', or pin the exact file with a hash or SRI.

  • Mediumdefault-src

    default-src is very permissive

    Every fetch directive you did not list explicitly (images, fonts, frames, workers, objects...) falls back to this broad source list.

    Fix: Start from default-src 'self' or 'none' and open specific directives.

  • Mediumframe-ancestors

    Missing frame-ancestors

    frame-ancestors controls who may embed your page, so it is the clickjacking defence. It does not fall back to default-src. Without it, only the legacy X-Frame-Options header can protect you.

    Fix: Add frame-ancestors 'none' (or 'self').

    Read more in the CSP reference
  • Lowscript-src

    'self' in script-src

    'self' trusts every file on your origin. If any endpoint on it reflects a callback parameter (JSONP) or serves user-uploaded JavaScript, it becomes a bypass. It is a reasonable baseline for static sites; with a nonce and 'strict-dynamic' CSP3 browsers ignore it.

  • Lowstyle-src

    'unsafe-inline' in style-src

    Inline styles allow CSS-based data exfiltration and UI redressing after an injection, but cannot run script. Many sites accept this trade-off for style attributes; it is far less severe than the same keyword in script-src.

  • Lowbase-uri

    Missing base-uri

    base-uri does not fall back to default-src. Without it, an injected <base href> can redirect every relative URL, including relative script paths, to an attacker's server.

    Fix: Add base-uri 'none' (or 'self' if you use <base>).

    Read more in the CSP reference
  • Lowform-action

    Missing form-action

    form-action does not fall back to default-src. An injected <form> (or a hijacked button) can post credentials to any host.

    Fix: Add form-action 'self' (list other hosts you submit to).

  • Notereport-uri

    report-uri is deprecated in favour of report-to

    report-uri still works in Chrome, Firefox and Safari. report-to (the Reporting API) is the successor but is not supported everywhere, so policies commonly send both. report-uri is ignored when report-to is supported.

    Read more in the CSP reference
  • Noteupgrade-insecure-requests

    No upgrade-insecure-requests

    Optional. It rewrites http:// subresource URLs to https:// before fetching, which helps when migrating an old site to HTTPS.

Parsed directives

DirectiveSources
default-src
*
script-src
'self''unsafe-inline''unsafe-eval'https://ajax.googleapis.comhttps://cdnjs.cloudflare.comdata:
style-src
'self''unsafe-inline'
report-uri
/csp-report

What is not set, and what covers it

Fetch directives you leave out fall back along a fixed chain, ending at default-src. A few directives never fall back, so leaving them out means no restriction at all.

DirectiveCovered by
child-srcdefault-src
connect-srcdefault-src
fenced-frame-srcdefault-src(chain: frame-src > child-src > default-src)
font-srcdefault-src
frame-srcdefault-src(chain: child-src > default-src)
img-srcdefault-src
manifest-srcdefault-src
media-srcdefault-src
object-srcdefault-src
script-src-attrscript-src(chain: script-src > default-src)
script-src-elemscript-src(chain: script-src > default-src)
style-src-attrstyle-src(chain: style-src > default-src)
style-src-elemstyle-src(chain: style-src > default-src)
worker-srcscript-src(chain: child-src > script-src > default-src)
base-uriNever falls back to default-src. Unrestricted until you set it.
form-actionNever falls back to default-src. Unrestricted until you set it.
frame-ancestorsNever falls back to default-src. Unrestricted until you set it.
sandboxNever falls back to default-src. Unrestricted until you set it.

No fallback: base-uri, form-action, frame-ancestors, sandbox, report-uri, report-to, upgrade-insecure-requests, require-trusted-types-for, trusted-types.

Link includes the policy text only.

How to read the result

Severity reflects how much a finding weakens protection against script injection, not whether a site is exploitable. An allowlisted host such as cdnjs.cloudflare.com is listed as a risk because published bypasses have used script gadgets on shared hosts. It is not proof that your page has an injection point.

The fastest route to a strong policy is a per-response nonce with 'strict-dynamic', plus object-src 'none' and base-uri 'none'. Roll it out with Content-Security-Policy-Report-Only first. The full background is in the Content-Security-Policy header reference. To check the headers a live site sends, use the Header Inspector or the Site Verifier.

Frequently asked questions

What does this CSP evaluator check?

It parses the policy and flags unsafe-inline and unsafe-eval in script-src, wildcard, https: and data: sources, missing object-src, base-uri and frame-ancestors, 'strict-dynamic' misuse, allowlisted hosts with known bypass risk, typos, unknown and duplicate directives, and deprecated reporting directives. It reads the policy text only; it cannot tell whether your pages still work under it.

Why does unsafe-inline not matter when I also have a nonce?

In browsers that support CSP2 and CSP3, 'unsafe-inline' is ignored in a source list that also contains a nonce or a hash. Keeping it only helps ancient CSP1 browsers. Without a nonce or hash, 'unsafe-inline' allows every inline script, which removes most of the protection against XSS.

Which directives fall back to default-src?

Fetch directives such as script-src, style-src, img-src, connect-src, font-src, media-src, object-src, manifest-src, frame-src and worker-src fall back to default-src when you omit them (frame-src and worker-src check child-src first, worker-src also script-src). base-uri, form-action, frame-ancestors and sandbox never fall back, so a default-src alone leaves them unrestricted.

Can I set frame-ancestors in a meta tag?

No. Browsers ignore frame-ancestors, report-uri and sandbox in a <meta http-equiv="Content-Security-Policy"> tag. To prevent clickjacking you must send the policy as an HTTP response header.

Is my policy sent to a server?

No. Parsing, grading and generation run entirely in your browser. A share link stores the policy in the URL hash, which the browser does not send to any server.

Browse /search