Content Security Policy (CSP) Blocking Inline Script or API Connection
Quick answer
A Content Security Policy violation always names the specific directive that blocked the resource and the exact source that was blocked — the browser console...
A Content Security Policy violation always names the specific directive that blocked the resource and the exact source that was blocked — the browser console message contains everything needed to fix it precisely, and the correct fix is almost always adjusting the CSP to explicitly allow the specific legitimate source, not removing the policy's protection wholesale.
The Problem
A page with CSP enabled shows a script failing to execute, or an API call failing, with a console error like:
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.
Refused to connect to 'https://api.example.com/data' because it violates the
following Content Security Policy directive: "connect-src 'self'".
Why It Happens
CSP is a browser-enforced security mechanism specifically designed to restrict which sources a page is allowed to load scripts, styles, connect to via fetch/XHR, and more from — its entire purpose is preventing exactly the kind of unrestricted execution that makes cross-site scripting (XSS) attacks dangerous. A CSP violation means your page is attempting to do something the currently configured policy doesn't explicitly permit:
script-srcviolations occur when a script tries to execute from a source (inline, or an external domain) not allowed by the policy — inline scripts are blocked by default under a strict CSP unless explicitly permitted, since inline script execution is one of the primary vectors CSP exists to restrictconnect-srcviolations occur when JavaScript attempts a fetch, XHR, WebSocket, or similar network connection to a domain not included in the allowed list — a common issue after adding a new third-party API integration without updating the CSP to match- A CSP that was copied from a template, documentation example, or a different project without being adjusted for your application's actual specific needs, resulting in either overly restrictive rules that block legitimate functionality, or overly permissive rules that don't provide meaningful protection
The Fix
For inline script violations, the most secure fix is moving the inline script to an external file instead, which is allowed under a standard 'self' policy without needing any special exception:
<!-- Instead of -->
<script>doSomething();</script>
<!-- Use an external file -->
<script src="/js/app.js"></script>
If inline scripts are genuinely necessary (some third-party integrations require them, or restructuring isn't immediately practical), use a nonce or hash-based approach rather than the broad, significantly less secure 'unsafe-inline' directive:
# Server generates a unique, unpredictable nonce per request
Content-Security-Policy: script-src 'self' 'nonce-r4nd0mVAlu3'
<script nonce="r4nd0mVAlu3">doSomething();</script>
The nonce must be genuinely random and regenerated for every single request/response — reusing the same nonce value across multiple requests defeats its entire security purpose, since a predictable or reused nonce could be exploited by an attacker attempting to inject their own inline script.
For legitimate connections to an external API, explicitly add that specific domain to the connect-src directive:
Content-Security-Policy: connect-src 'self' https://api.example.com
Be as specific as possible about exactly which domains are actually needed, rather than using an overly broad wildcard — a policy allowing every subdomain of a broad, shared domain (like a wildcard covering an entire cloud provider's hosting domain) provides considerably less protection than one listing the exact, specific domains your application genuinely needs to communicate with:
# More specific and protective
Content-Security-Policy: connect-src 'self' https://api.example.com https://analytics.example.com
# Broader, less protective (avoid unless genuinely necessary)
Content-Security-Policy: connect-src 'self' https://*.example.com
If you're adding multiple new third-party integrations over time, review and audit your CSP directives periodically rather than only reactively adding exceptions each time something breaks — a CSP that's grown through many one-off additions without periodic review can accumulate broader-than-necessary permissions over time, gradually eroding the actual security benefit the policy is meant to provide.
Still Not Working?
If you've added the specific domain to the appropriate directive but the violation persists, check whether your CSP is being set in multiple places with conflicting values — a CSP header set both by your application code and by your web server or CDN configuration can result in the browser enforcing the more restrictive of the two (or, depending on exact header combination behavior, producing genuinely unexpected results), similar in spirit to the duplicate-header issues that affect other security-relevant headers. Confirm there's only one, consistent, intentional source of your CSP header by inspecting the actual response headers directly:
curl -I https://yoursite.com | grep -i content-security-policy
If this shows more than one CSP header, or a single header with directives that don't match what you expect from your own application configuration, there's a second, unaccounted-for source setting or modifying the policy somewhere else in your infrastructure that needs to be identified and reconciled with your intended configuration.