← All checks
SecurityTypical severity: Medium

Weak CSP Scanner

Detects unsafe directives like 'unsafe-inline' or 'unsafe-eval' that weaken your CSP's XSS protection.

What it checks

This scanner analyzes your Content-Security-Policy for unsafe directives like unsafe-inline or unsafe-eval. These options loosen the policy so much that it stops protecting you effectively. The scanner only reviews how the CSP is defined, it does not rewrite it.

Why it matters

A CSP with these directives barely stops the script injection (XSS) attacks it is meant to block. It gives a false sense of security: it looks like you are protected, but the protection is hollow. An attacker who injects code can run it without trouble.

How to fix it

Remove unsafe-inline and unsafe-eval from your policy and replace them with a nonce- or hash-based approach for the scripts you genuinely need. Start from a strict policy and allow only what is essential. Test changes carefully, since a poorly tuned CSP can break legitimate functionality.

How this check works

This check only acts if your site already sends a Content-Security-Policy header; if it does not, the headers scanner flags that. Scanaris reads the full policy and looks for the two words that hollow it out: 'unsafe-inline', which allows running any script or style written directly in the HTML, and 'unsafe-eval', which allows turning text into code with eval and friends. If either appears, it opens a low-severity finding with the list of weaknesses found. It is low because an imperfect CSP is still better than none, but the protection against script injection, which is the CSP's reason to exist, is almost cancelled.

Why it matters

A strict CSP makes the browser refuse to run a <script> even if an attacker manages to get one into your page (through an unsanitized comment, a reflected parameter or a compromised library). With 'unsafe-inline' in script-src, that injected script runs anyway: the header is there, the lock looks closed, but the door is open. Where the word sits matters: in script-src it is serious; in style-src it is a much smaller risk that many sites accept for their inline styles.

How to fix it

1. Nonces for inline scripts

A nonce is a random value, different on every request, that you put in the header and in every legitimate <script> tag. The browser runs only the scripts carrying that value; an injected script does not know it.

Content-Security-Policy: script-src 'nonce-R4nd0m' 'strict-dynamic'; object-src 'none'; base-uri 'self'

Next.js does it in the middleware, generating the nonce and passing it to the header and the components; Nuxt, with a server plugin that injects it in every response (that is what Scanaris does); Express, with a middleware that stores it in res.locals and prints it in the templates.

2. Hashes for fixed scripts

If an inline script never changes, compute its SHA-256 hash and put it in the policy: 'sha256-…'. It works for small snippets, like a tag manager's, without setting up nonces.

3. Move code into files

onclick="…" handlers and script blocks in the HTML are the usual reason for needing 'unsafe-inline'. Move them to .js files served from your domain and the need disappears.

4. Remove unsafe-eval

It is usually demanded by an old library or a framework's development mode that slipped into production. Check in the browser console what asks for it and update or replace that piece.

5. Roll out in report-only mode

Publish the new policy first as Content-Security-Policy-Report-Only with a report-to or report-uri directive pointing at an endpoint of yours. Collect for a few days what it would block, adjust, and when the reports are clean switch it to the enforcing header.

Check it is fixed

curl -sI https://yourdomain.com | grep -i "content-security-policy"

Neither 'unsafe-inline' nor 'unsafe-eval' should appear in script-src. Then browse your site with the console open: any block shows up there with the directive that caused it. The full theory is in HTTP security headers explained for humans.

Frequently asked questions

I use Tailwind or inline styles. Do I have to remove unsafe-inline from style-src?

Desirable but not urgent. Inline styles do not run code. Prioritise script-src; a policy with 'unsafe-inline' only in style-src protects against what matters.

Google Tag Manager or a support chat force me to relax the policy.

Almost all of them have CSP documentation: they accept a nonce or publish the hashes and domains they need. Add their origins to script-src and connect-src instead of opening everything.

Will the CSP break my site?

Only if you switch it to enforcing without testing. That is what report-only mode is for: it shows you what would break without breaking it.

Check it on your site

Scan your site free and see if this and 44 other checks pass, with a fix prompt for every issue.

Scan my site free

From the blog

Related checks