in HTML, javascript: URIs, inline event handlers (onclick='...'), eval/new Function — all fail silently. Strict CSP needs nonces or hashes for legitimate inline. frame-src blocked: any iframe (payment widgets, embedded videos, OAuth popups, third-party SSO) won't load. For embeds, host them on an allowed domain or coordinate with the merchant to add your domain to frame-src and script-src. Test with the merchant's CSP enabled in staging.","answerCount":1,"upvoteCount":0,"datePublished":"2026-05-11T04:48:06.136775+00:00","dateModified":"2026-05-18T09:58:06.688474+00:00","author":{"@type":"Organization","name":"InterviewLane","url":"https://interviewlane.com/"},"acceptedAnswer":{"@type":"Answer","text":"Content Security Policy (CSP) is a security header that whitelists allowed resources. When a merchant (or any host) sets a strict CSP, embedded widgets break unless they're explicitly allowed. What inline script restrictions break Strict CSP without blocks: 1. Inline blocks: 2. Inline event…","url":"https://interviewlane.com/questions/what-breaks-when-strict-csp-blocks-inline-scripts-and-frames","upvoteCount":0,"datePublished":"2026-05-11T04:48:06.136775+00:00","author":{"@type":"Organization","name":"InterviewLane","url":"https://interviewlane.com/"}}}},{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://interviewlane.com/"},{"@type":"ListItem","position":2,"name":"Categories","item":"https://interviewlane.com/categories"},{"@type":"ListItem","position":3,"name":"Security","item":"https://interviewlane.com/categories/security"},{"@type":"ListItem","position":4,"name":"What breaks when a strict CSP blocks inline scripts and frame sources?","item":"https://interviewlane.com/questions/what-breaks-when-strict-csp-blocks-inline-scripts-and-frames"}]}]
Back to Security
Security
easy
mid

What breaks when a strict CSP blocks inline scripts and frame sources?

Inline scripts blocked: any <script>...</script> in HTML, javascript: URIs, inline event handlers (onclick='...'), eval/new Function — all fail silently. Strict CSP needs nonces or hashes for legitimate inline. frame-src blocked: any iframe (payment widgets, embedded videos, OAuth popups, third-party SSO) won't load. For embeds, host them on an allowed domain or coordinate with the merchant to add your domain to frame-src and script-src. Test with the merchant's CSP enabled in staging.

9 min read·~5 min to think through

Content Security Policy (CSP) is a security header that whitelists allowed resources. When a merchant (or any host) sets a strict CSP, embedded widgets break unless they're explicitly allowed.

What inline-script restrictions break

Strict CSP without 'unsafe-inline' blocks:

1. Inline <script> blocks:

html
<script>doStuff();</script>   ← blocked

2. Inline event handlers in HTML:

html
<button onclick="doStuff()">Click</button>   ← blocked

3. javascript: URIs:

html
<a href="javascript:doStuff()">Click</a>   ← blocked

4. eval() and new Function():

js
eval('1 + 1')               ← blocked without 'unsafe-eval'
new Function('return 1')();

5. Inline styles (if style-src is similarly strict):

html
<div style="color: red">…</div>   ← may be blocked

6. Dynamic script injection (often used by analytics/tag managers):

js
const s = document.createElement('script');
s.innerHTML = '…';
document.head.appendChild(s);   ← blocked if script content is inline

How to legitimately do inline under strict CSP

Nonces: server generates a fresh random nonce per response and includes it in CSP + each allowed inline script tag:

ts
Content-Security-Policy: script-src 'self' 'nonce-abc123'
html
<script nonce="abc123">init();</script>

Hashes: precompute SHA-256 of the inline script body, list in CSP:

ts
Content-Security-Policy: script-src 'self' 'sha256-xyz...'

Strict-dynamic: trust scripts loaded by already-trusted scripts:

ts
Content-Security-Policy: script-src 'self' 'strict-dynamic' 'nonce-abc123'

What frame-src restrictions break

frame-src (or child-src) controls which origins can be embedded as iframes.

Common breakage on strict frame-src:

  • Payment widgets: Stripe Elements (iframes for card input), PayPal buttons, Apple Pay popups.
  • Embedded videos: YouTube, Vimeo, Twitch.
  • Embedded maps: Google Maps iframe embeds, OpenStreetMap.
  • Social embeds: tweets, Instagram, Facebook posts.
  • OAuth flows: third-party SSO popups (Google, GitHub, Microsoft).
  • Chat widgets: Intercom, Drift, Zendesk.
  • Analytics: some heatmap and session-replay tools (e.g., FullStory) iframe in.
  • Captchas: reCAPTCHA, hCaptcha load in iframes.

What to do when integrating

If you're the embedded widget asking a merchant to embed you:

  1. Document your CSP requirements: tell merchants exactly which directives to add.
  • script-src https://js.yourservice.com
  • frame-src https://yourservice.com
  • connect-src https://api.yourservice.com
  • img-src https://images.yourservice.com
  1. Minimize inline code so merchants don't need 'unsafe-inline'.
  2. Use nonces or external scripts instead of inline.
  3. Provide nonced inline option if you must inline (publish-time hash, runtime nonce).
  4. Test on merchant's staging CSP before going live.

If you're the merchant setting CSP:

  1. Start in report-only mode to find what would break:

`` Content-Security-Policy-Report-Only: script-src 'self'; report-uri /csp-report ``

  1. Enumerate trusted origins from third parties you use.
  2. Use nonces for legitimate inline rather than 'unsafe-inline'.
  3. Adopt strict-dynamic to simplify the policy.
  4. Iterate: tighten the policy as you remove inline scripts and reduce third-party sprawl.

Debugging

When a widget breaks under CSP:

  • Browser console shows: Refused to execute inline script because it violates the following Content Security Policy directive…
  • Network panel: blocked resources show (blocked:csp) or similar.
  • Use report-uri / report-to to collect violations from real users.

Other related CSP directives

  • default-src — fallback for unspecified directives.
  • script-src — JS.
  • style-src — CSS.
  • img-src — images.
  • font-src — fonts.
  • connect-src — XHR/fetch/WebSocket.
  • frame-src — iframes.
  • frame-ancestors — who can embed YOU as iframe.
  • form-action — where forms can submit.
  • base-uri<base> tag values.

Bonus: X-Frame-Options + frame-ancestors

If the merchant doesn't want to be embedded:

ts
Content-Security-Policy: frame-ancestors 'self'
X-Frame-Options: SAMEORIGIN

Prevents anyone from embedding their site in an iframe. Defense against clickjacking.

Mental model

CSP is a contract between the page and the browser. Strict CSP closes most XSS attack surfaces, but it also breaks anything that uses inline JS, eval, or unallowed external origins. As a widget vendor, design for CSP-friendliness; as a merchant, adopt CSP gradually with report-only first.

Follow-up questions

  • How do nonces work in CSP?
  • What's strict-dynamic and why is it easier than nonces alone?
  • How do you collect CSP violation reports?
  • What's the difference between frame-src and frame-ancestors?

Common mistakes

  • Shipping inline scripts when targeting strict-CSP customers.
  • Using eval / new Function in libraries.
  • Not documenting CSP requirements for integrators.
  • Adding 'unsafe-inline' to make things work — defeats CSP's purpose.
  • Forgetting report-only mode during rollout.
  • Wildcard origins ('*') — defeats the whitelist.

Performance considerations

  • CSP has negligible perf overhead. The cost of CSP violations (broken widgets, failed payments) is far higher. Use report-only during rollout to catch issues without breaking production.

Edge cases

  • <base> tag injection — base-uri directive matters.
  • Service worker scripts have their own CSP rules.
  • WASM execution may need wasm-unsafe-eval.
  • Third-party tags that inject more scripts dynamically — strict-dynamic helps.
  • Stripe Elements specifically requires script-src 'self' js.stripe.com + frame-src js.stripe.com + connect-src api.stripe.com.

Real-world examples

  • Stripe documents exact CSP directives merchants need to add.
  • YouTube embeds require frame-src youtube.com.
  • GitHub uses strict CSP with nonces.
  • Google Search uses very tight CSP across its product surface.

Senior engineer discussion

Seniors design widgets to be CSP-friendly from day one (external scripts, no eval, no inline). For their own apps, they adopt CSP gradually via report-only, using nonces and strict-dynamic to avoid 'unsafe-inline.' They also know which third parties impose real CSP costs and weigh them in vendor selection.

Related questions