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.