There’s nothing quite like deploying a CSP policy to production and watching your analytics break, your chat widget disappear, and your forms stop working. All at the same time.
This guide is about surviving that experience and fixing things quickly.
Where to Find CSP Violations
Chrome
Open DevTools (F12) → Console tab. CSP violations show up as red errors:
Refused to execute inline script because it violates the following
Content Security Policy directive: "script-src 'self'"
For a more detailed view: DevTools → Application → Content Security Policy. This shows you the current policy and a log of violations.
Firefox
DevTools (F12) → Console tab. Firefox uses slightly different wording:
Content Security Policy: The page's settings blocked the loading
of a resource at inline ("script-src").
Safari
Web Inspector → Console tab. Similar to Firefox.
The 8 Most Common Violations (And How to Fix Them)
1. “Refused to execute inline script”
Refused to execute inline script because it violates the following
Content Security Policy directive: "script-src 'self'"
What happened: You have a <script> tag with code directly in it, and your CSP doesn’t allow inline scripts.
Fix options:
- Move the code to an external
.jsfile:<script src="/js/my-script.js"></script> - Add a nonce to the script tag:
<script nonce="YOUR_NONCE">...</script> - Add
'unsafe-inline'to script-src (least secure, avoid if possible)
2. “Refused to apply inline style”
Refused to apply inline style because it violates the following
Content Security Policy directive: "style-src 'self'"
What happened: A style="..." attribute or <style> tag is being blocked.
Fix: Add 'unsafe-inline' to style-src. This is a common and generally accepted compromise — CSS can’t execute JavaScript.
3. “Refused to evaluate a string as JavaScript”
Refused to evaluate a string as JavaScript because 'unsafe-eval'
is not an allowed source of script
What happened: Something is calling eval(), new Function(), setTimeout("string"), or setInterval("string").
Fix: Find the code using eval and refactor it. Common culprits:
- Old jQuery plugins
- Template engines (handlebars without precompilation)
- JSON parsing (use
JSON.parse()instead ofeval())
If you absolutely can’t remove it, add 'unsafe-eval' to script-src. But understand this significantly weakens XSS protection.
4. “Refused to load the script”
Refused to load the script 'https://cdn.example.com/script.js'
because it violates the following Content Security Policy directive
What happened: A script is being loaded from a domain not in your script-src.
Fix: Add the domain to script-src:
script-src 'self' https://cdn.example.com
5. “Refused to load the image”
Refused to load the image 'data:image/png;base64,...' because it
violates the following Content Security Policy directive
What happened: A data URI image (base64 encoded, inline SVG) is being blocked.
Fix: Add data: to img-src:
img-src 'self' data: https:
6. “Refused to connect to”
Refused to connect to 'https://api.example.com/data' because it
violates the following Content Security Policy directive
What happened: A JavaScript fetch() or XMLHttpRequest is trying to reach a domain not in connect-src.
Fix: Add the domain to connect-src:
connect-src 'self' https://api.example.com
7. “Refused to load the font”
Refused to load the font 'https://fonts.gstatic.com/s/...' because
it violates the following Content Security Policy directive
What happened: Google Fonts (or another font service) is being blocked.
Fix: Add font domains:
font-src 'self' https://fonts.gstatic.com
style-src 'self' https://fonts.googleapis.com
8. “Refused to frame”
Refused to display 'https://youtube.com/embed/...' in a frame
because it violates the following Content Security Policy directive
What happened: An iframe is trying to load content from a domain not in frame-src.
Fix: Add the domain to frame-src:
frame-src 'self' https://www.youtube.com
Systematic Debugging Approach
When you have dozens of violations, don’t try to fix them one by one. Use this approach:
1. Filter by directive. Group violations by the directive they violate (script-src, style-src, etc.). This shows you which part of your policy needs the most work.
2. Filter by source. Group by the blocked URI. You’ll often find that a single third-party service causes most violations.
3. Check if it’s necessary. Before adding a domain to your policy, ask: do we actually need this? I’ve found analytics scripts from discontinued A/B tests, old chat widgets that were replaced months ago, and tracking pixels nobody remembers adding. Remove the dead code first.
4. Add one domain at a time. Don’t bulk-add domains. Add one, test, move on.
Using the Browser’s CSP Report
Both Chrome and Firefox can send detailed violation reports. In Chrome:
- DevTools → Application → Content Security Policy
- Click “Send violation reports” (a checkbox)
- Open the “View reports” panel
This shows you structured violation data that’s much easier to analyze than console errors.
Server-Side Reporting
For ongoing monitoring, set up a report endpoint:
Content-Security-Policy: ...; report-uri /api/csp-report
And log the reports server-side. This way you catch violations from real users, not just yourself in DevTools.
Quick Reference: Common Services and Their CSP Requirements
| Service | script-src | style-src | img-src | connect-src | frame-src |
|---|---|---|---|---|---|
| Google Analytics | googletagmanager.com | google-analytics.com | google-analytics.com | ||
| Google Tag Manager | googletagmanager.com | googletagmanager.com | googletagmanager.com | ||
| Stripe | js.stripe.com | api.stripe.com | js.stripe.com | ||
| Intercom | widget.intercom.io, intercomcdn.com | intercomcdn.com | api-iam.intercom.io | intercom-sheets.com | |
| Hotjar | static.hotjar.com, script.hotjar.com | static.hotjar.com | *.hotjar.com | ||
| hCaptcha | js.hcaptcha.com, hcaptcha.com | *.hcaptcha.com | *.hcaptcha.com |
Verify Your Fix
After fixing violations, use headertest.com to confirm your CSP is properly configured.