How to remove unsafe-inline?
csp-unsafe-inline-present global
The issue
A Content Security Policy that allows 'unsafe-inline' for scripts lets every inline script and event handler run, including injected ones. Since injected code is usually inline, the policy no longer does the job it is most often there for, while it still looks like it does.
The cause is usually inline code in templates or third-party snippets that broke when the policy was first enforced. 'unsafe-inline' was the quick way to make it work.
Scope
The keyword applies to the whole document the policy covers. It is normally part of the shared policy, so it applies to every page, including pages with no inline code of their own.
How to check you have it
- In probeo: a policy that lets inline scripts run is reported as
csp:script-src-unsafe-inline, graded major, and one that lets inline styles apply ascsp:style-src-unsafe-inline, graded minor. A nonce, a hash or'strict-dynamic'alongside'unsafe-inline'makes the browser ignore it, and probeo doesn’t report it then. - By hand: run
curl -sI https://your-site.example/ | grep -i content-security-policyand look for'unsafe-inline'inscript-srcandstyle-src, or indefault-srcwhere those are absent. - With a tool: Google’s CSP Evaluator reports
'unsafe-inline'in a policy.
The fix
Remove 'unsafe-inline' from script-src once inline scripts and handlers are gone or carry a nonce or hash.
Move inline scripts into files, replace on… attributes with addEventListener, and give anything that must stay inline a nonce or hash. Test the result as a report-only policy first. Treat style-src the same way afterward.
Done when: the enforced policy doesn’t allow inline scripts without a nonce or hash, and the check above comes back clean.
Do not
- Do not keep
'unsafe-inline'as the permanent configuration. - Do not assume a policy with
'unsafe-inline'protects against injected scripts. - Do not add
'unsafe-inline'to silence violations without finding their cause. - Do not forget inline event handlers when removing it.
FAQ
Why is unsafe-inline considered worse than no CSP at all?
It isn’t worse in what the browser allows; the rest of the policy still restricts where external scripts come from. What makes it misleading is that the policy looks like protection against injected scripts when it isn’t.
Can unsafe-inline be used temporarily during CSP deployment?
Yes, as a step. Enforce the policy with it, fix inline code, test the policy without it in report-only mode, then remove it.
What if third-party scripts inject inline code?
They break once 'unsafe-inline' is gone, unless the policy uses 'strict-dynamic', which trusts scripts that a trusted script adds. Otherwise ask the vendor for a version that supports nonces, or replace it.
Does removing unsafe-inline break all sites initially?
It breaks whatever inline code the site has, which ranges from nothing to a great deal. Running the strict policy in report-only mode first shows exactly what.
How does unsafe-inline interact with nonces and hashes?
When script-src holds a nonce or a hash, browsers ignore 'unsafe-inline' in it. Inline scripts then need a matching nonce or hash, and inline event handlers are blocked. 'unsafe-inline' is often left in for older browsers that don’t understand nonces.
What about unsafe-inline in style-src?
It matters less than in script-src, since CSS can’t run JavaScript. Injected styles can still change what a page shows or load URLs that leak information. Remove it from script-src first.
Which product detects this
Probeo checks this on every page of your site as part of Site Clarity. This page explains one instance; the product tells you every page that has it.