headers error

CSP: Refused to execute inline script — script-src violation

The error

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

What it means

A <script> tag with code directly inside (or an inline event handler like onclick) was blocked because your CSP only allows scripts from listed origins.

Strict CSP blocks inline JavaScript because it’s the most common XSS vector. To allow specific inline scripts, you mark each with a per-request nonce that the policy lists, or a SHA hash of the script body.

The fix

Next.js middleware: per-request nonce
// app/middleware.ts
import { NextResponse } from 'next/server';

export function middleware() {
  const nonce = crypto.randomUUID();
  const csp = [
    `default-src 'self'`,
    `script-src 'self' 'nonce-${nonce}' 'strict-dynamic'`,
    `style-src 'self' 'unsafe-inline'`,
  ].join('; ');

  const res = NextResponse.next();
  res.headers.set('Content-Security-Policy', csp);
  res.headers.set('x-nonce', nonce);  // your layout reads this and applies it
  return res;
}

Also check

Common adjacent root causes when the obvious fix doesn’t work.

  • 01Inline event handlers (onclick="...") are also blocked. Move them to addEventListener calls.
  • 02Tag managers (GTM, Segment) inject inline scripts — most support nonce passthrough; configure it.
  • 03Setting 'unsafe-inline' makes the policy nearly worthless against XSS — only use it as a last resort.

Scan for related issues

This error is in our headers scanner. Run a free scan to find what else is misconfigured in the same area.

FAQ

Frequently asked questions

Can't I just add 'unsafe-inline' and move on?
You can — your CSP just becomes near-useless against XSS, which is why the policy exists. Use a nonce instead. It's not much harder once your framework supports it (Next.js 15 does natively).
What does strict-dynamic do?
It says: trust scripts loaded by the trusted nonce-marked script. So a tag manager loaded via nonce can then load its own subresources without each needing its own nonce. It massively simplifies CSP.