sfw/fix
Refused to execute inline script medium

"Refused to execute inline script because it violates the following Content Security Policy directive"

A Content-Security-Policy script-src directive without 'unsafe-inline' blocked an inline <script> or event handler.

What you see

Refused to execute inline script because it violates the
following Content Security Policy directive: "script-src 'self'".
Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a
nonce ('nonce-...') is required to enable inline execution.

What’s actually happening

A feature breaks — a button does nothing, a widget never initializes, analytics stop firing — and the browser console shows the refusal in red. It only affects inline code: <script> blocks written directly in the HTML and on* attributes like onclick. External .js files referenced with src load fine. The page itself renders; only the inline JavaScript is dead.

Common causes

  • The CSP script-src (or default-src) lists sources but omits 'unsafe-inline', which is the default-deny behavior for inline code
  • An inline <script>...</script> block embedded in the HTML
  • An HTML event-handler attribute such as onclick=, onload=, or onerror=
  • A third-party tag (ad, chat, A/B test) that injects inline script after load
  • A javascript: URL in an href or form action, which CSP also treats as inline

How to fix it

  1. Move the code into an external fileCut the inline JavaScript into its own .js, serve it from an origin already in script-src (or 'self'), and reference it with <script src>. Replace onclick="foo()" with addEventListener in that file. This is the cleanest fix and needs no CSP change.
  2. Add a per-request nonce if the script must stay inlineGenerate a fresh random nonce on every response, put it in the header as script-src 'nonce-RANDOM', and add nonce="RANDOM" to the <script> tag. The nonce must be unguessable and regenerated each request — a static nonce is the same as 'unsafe-inline'.
  3. Whitelist the exact script by SHA-256 hashFor a fixed inline block you don't control by template, hash its exact bytes and add 'sha256-...' to script-src. The console message usually prints the expected hash. Any change to the script content breaks the hash, so this fits static snippets only.
  4. Avoid 'unsafe-inline' unless nothing else worksAdding 'unsafe-inline' makes the error vanish but removes the XSS protection CSP exists to provide. If you must use it as a stopgap, scope it narrowly and treat it as tech debt. Note that a nonce or hash in the same directive causes browsers to ignore 'unsafe-inline'.

Stop it recurring

Deploy CSP in Content-Security-Policy-Report-Only mode first and collect violation reports, so you catch every inline script before the policy enforces.

Related errors