How to Fix "Refused to execute inline script because it violates Content Security Policy" (Complete 2026 Guide)
Resolve Refused to execute inline script CSP errors in Next.js, React, and NGINX using nonces, sha256 hashes, and strict-dynamic directives.
1. Root Cause Analysis (Engine-Level Breakdown)
When modern JavaScript engines (V8 in Chrome/Node.js, JavaScriptCore in Safari, and SpiderMonkey in Firefox) encounter this failure condition, execution halts or falls back to degraded behavior due to the following primary triggers:
- Inline `<script>` tag or inline event handler (`onclick=...`) executed without a cryptographic nonce matching the server CSP response header.
- Framework SSR HTML hydration injecting inline JSON state blobs without safe serialized script tags or nonces.
- Using `unsafe-inline` while also declaring a nonce or hash (modern browsers ignore `unsafe-inline` when a nonce or hash is present).
In high-scale production systems, this error rarely occurs during local development because local environments lack network latency, third-party browser extensions, complex caching proxies, and production minification transforms that uncover timing race conditions.
2. Verified Production Solutions
The following code recipes provide immediate and architectural fixes for this error:
// Next.js Middleware Nonce Generation (Next.js 14 & 15 App Router):
import { NextRequest, NextResponse } from 'next/server';
export function middleware(request: NextRequest) {
const nonce = Buffer.from(crypto.randomUUID()).toString('base64');
const cspHeader = `
default-src 'self';
script-src 'self' 'nonce-${nonce}' 'strict-dynamic' https: 'unsafe-inline';
style-src 'self' 'unsafe-inline';
img-src 'self' blob: data: https:;
connect-src 'self' wss: https:;
font-src 'self';
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
upgrade-insecure-requests;
`.replace(/\s{2,}/g, ' ').trim();
const requestHeaders = new Headers(request.headers);
requestHeaders.set('x-nonce', nonce);
requestHeaders.set('Content-Security-Policy', cspHeader);
const response = NextResponse.next({ request: { headers: requestHeaders } });
response.headers.set('Content-Security-Policy', cspHeader);
return response;
}
3. Step-by-Step Resolution Workflow
Follow this structured checklist to resolve and prevent this error in your CI/CD pipeline:
Step 1: Inspect the exact blocked inline script in Chrome DevTools Console
Open the console and identify whether the blocked script is an analytics snippet or an inline framework state hydration payload.
Step 2: Implement dynamic cryptographic nonces in server middleware
Generate a random base64 nonce per HTTP request and pass it to both the CSP header and the `<script nonce="...">` element.
Step 3: Adopt strict-dynamic for third-party tag managers
Use strict-dynamic so that dynamically injected scripts from verified loaders inherit trust without hardcoding fragile domain whitelists.
🔍 How ReMOAT Resolves This Error Where It Actually Happens
ReMOAT automatically audits Content Security Policy violations in remote sessions and alerts you to blocked scripts and connect-src WebRTC drops.
Inspect This Bug in ReMOAT DevTools →