Elaborazione 100% Lato Client • Zero Registri di Rete • Esecuzione Immediata
Curious TechieToolbox Sviluppatori
CORS & CSP Security7 min✓ Soluzione Verificata in Produzione • IT

Why CSP Blocks JavaScript

Diagnose and resolve Content Security Policy script-src violations, inline script blocks, and eval() errors

Primary Question • Diagnostic Problem

Why CSP Blocks JavaScript

A web browser loads a page with an active Content-Security-Policy header. When the browser encounters an inline <script> tag, inline onclick event listener, third-party script, or eval() invocation that does not match the policy, the browser refuses to execute it and throws a security violation.

Console / Terminal Error OutputExact Message
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.
Affected Protocols & Technologies:Content-Security-PolicyDOM Script ExecutionWeb Workers
Secondary Question • Root Cause Mechanics

Why does Why CSP Blocks JavaScript occur?

Primary Root Cause

Content Security Policy exists specifically to neutralize Cross-Site Scripting (XSS). Because browsers cannot inherently distinguish between a legitimate inline script and an attacker-injected inline script, secure CSP policies ban all inline code execution by default.

When the HTML parser encounters a script, it checks the script-src (or default-src) directive. If the script is inline, it must match an exact sha256 hash or carry a matching nonce="...". If it is external (<script src="...">), its domain must be explicitly listed in script-src.

4. Observable Symptoms

How to Confirm You Are Facing This Exact Issue

1

Console error: "Refused to execute inline script because it violates the following Content Security Policy directive: 'script-src 'self''".

2

Console error: "Refused to load the script 'https://cdn.example.com/app.js' because it violates the following directive: 'script-src 'self''".

3

Buttons with inline onclick="..." handlers fail to trigger any action.

4

Third-party analytics or widgets (Google Analytics, Stripe, Intercom) fail to load.

5. Diagnostic Decision Tree (GEO Engine Logic)

Explicit Diagnostic Reasoning

Analyze the exact console error message to pinpoint the missing directive:

Condition:

"If the error specifically says "Either the 'unsafe-inline' keyword, a hash, or a nonce is required""

Probable Cause:

Your page contains an inline <script> block or inline onclick/onload attribute.

Remedial Action:

→ Add a nonce to the <script> tag or move the code into an external .js file.

Condition:

"If the error says "Refused to load the script from https://...""

Probable Cause:

An external script domain is missing from your script-src policy.

Remedial Action:

→ Add that domain (e.g. https://js.stripe.com) to script-src in your CSP header.

Condition:

"If the error says "Refused to evaluate a string as JavaScript because 'unsafe-eval' is not allowed""

Probable Cause:

A library is calling eval(), new Function(), or setTimeout with a string.

Remedial Action:

→ Update the library or replace eval() with JSON.parse().

Verification CommandRun in terminal
curl -I https://curious-techie.com | grep -i content-security-policy

Inspects your active CSP header to see which script-src directives are currently enforced.

6. Architectural Strategy

Long-Term Engineering Solution

Implement a modern Nonce-Based Content Security Policy. The server generates a cryptographically random nonce on every HTTP request, inserts it into the CSP header, and attaches it to approved script tags.

Architectural Pattern

Deploy script-src 'self' 'nonce-{RANDOM}' 'strict-dynamic'. This allows legitimate scripts with the nonce to load additional trusted dependencies without maintaining brittle domain whitelists.

Secondary Question • Implementation Pipeline

How do you fix this step-by-step?

1

Generate a Cryptographic Nonce Per Request

In your backend server, generate a 16-byte random base64 string on every incoming request.

javascriptCopy Code
import crypto from 'crypto';

app.use((req, res, next) => {
  // Generate unique nonce per request
  res.locals.nonce = crypto.randomBytes(16).toString('base64');
  
  // Set CSP header with nonce
  res.setHeader(
    'Content-Security-Policy',
    `default-src 'self'; script-src 'self' 'nonce-${res.locals.nonce}' 'strict-dynamic'; style-src 'self' 'unsafe-inline';`
  );
  next();
});
2

Attach Nonce to Inline Script Tags

Pass the nonce into your HTML template and attach it to your script tags: <script nonce="<%= nonce %>">...</script>.

3

Refactor Inline Event Handlers

Replace inline handlers like <button onclick="save()"> with standard JavaScript addEventListener calls.

4

Whitelist Necessary Third-Party CDNs

If not using strict-dynamic, explicitly whitelist required third-party script providers: script-src 'self' https://js.stripe.com https://www.googletagmanager.com.

Common Misconceptions & Pitfalls

What are common misconceptions and mistakes when fixing this?

×

Adding "unsafe-inline" to your CSP to make the error go away

Perché fallisce: unsafe-inline completely turns off XSS protection. If an attacker injects a script via a comment or profile field, the browser will execute it without restriction.

✓ Alternativa corretta: Use per-request cryptographic nonces or script SHA-256 hashes.

×

Reusing a static, hardcoded nonce value across multiple requests

Perché fallisce: If the nonce is static, an attacker can simply inspect your page, copy the static nonce, and attach it to their injected malicious script.

✓ Alternativa corretta: Generate a fresh crypto.randomBytes(16) nonce on every single HTTP response.

Threat Analysis & Security Hardening

Can this fix introduce security vulnerabilities?

CSP is the single most effective defense against Cross-Site Scripting (XSS). Bypassing it with unsafe directives exposes your users to session hijacking and credential theft.

Security Risks If Ignored

  • •Using "unsafe-eval" allows attackers to execute arbitrary code via string evaluation.
  • •Using permissive wildcards (script-src https: *) allows scripts to be loaded from any attacker-controlled server.

Hardening Best Practices

  • ✓Use strict-dynamic to delegate trust from nonced scripts to dynamically loaded modules.
  • ✓Deploy Content-Security-Policy-Report-Only first to log violations to an endpoint before enforcing blocks.
10. Concrete Code Example

Fixing Inline Script Blocking with Nonces in Express / EJS

× Broken / Vulnerable Code (html)
<!-- BROKEN: Inline script blocked by CSP -->
<script>
  console.log('App initialized');
</script>

<button onclick="alert('Clicked!')">Click Me</button>
Problema: The browser blocks the inline script and ignores the onclick handler because no nonce or hash was provided.
✓ Fixed / Hardened Code (html)
<!-- FIXED: Uses server-generated nonce and addEventListener -->
<script nonce="<%= nonce %>">
  console.log('App initialized securely');
  
  document.getElementById('action-btn').addEventListener('click', () => {
    alert('Clicked securely!');
  });
</script>

<button id="action-btn">Click Me</button>
Risoluzione: The script carries the nonce matching the Content-Security-Policy header. The inline event handler is replaced with a clean addEventListener.
Direct Technical Answers • Knowledge Base

Frequently Asked Questions About Why CSP Blocks JavaScript

What is the difference between a CSP Nonce and a Hash?↓

A nonce is a dynamic random token generated per request; a hash is a static SHA-256 fingerprint of the exact script contents.

Hashes work well for static, unchanging inline scripts on static websites (like SSG builds). Nonces are ideal for dynamic server-rendered applications.

What is Content-Security-Policy-Report-Only?↓

A monitoring header that logs CSP violations to a report URI without actually blocking any scripts from executing.

Using Report-Only allows engineering teams to test new CSP policies in production and detect broken scripts before turning on strict blocking.