Content Security Policy
Content Security Policy (CSP) is an HTTP response header that tells the browser which sources a page may load resources from. Anything outside the policy is blocked before the request goes out, and the browser writes a refusal to the console.
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.jsdelivr.net;
style-src 'self' 'unsafe-inline'; img-src 'self' data:; frame-ancestors 'none'
The directives that decide whether a report renders
| Directive | Governs | Symptom when it blocks |
|---|---|---|
script-src |
JavaScript | Dead tables, empty chart boxes |
style-src |
CSS, including <style> |
Unstyled wall of text |
img-src |
Images, data: URIs |
Broken image placeholders |
connect-src |
fetch, XHR, WebSocket |
Blank shell — the data never loads |
font-src |
Web fonts | Fallback glyphs, shifted layout |
frame-ancestors |
Who may frame the page | Blank iframe in Notion/Confluence |
Generated reports trip script-src most often, because nearly every
chart library ships as a CDN <script> tag and nearly every corporate
host allows only 'self'.
Reading a violation
The console message names the cause precisely:
Refused to load the script 'https://cdn.plot.ly/plotly-2.27.0.min.js'
because it violates the following Content Security Policy directive: "script-src 'self'".
That is a CSP block. This is not:
Mixed Content: The page at 'https://…' was loaded over HTTPS, but requested
an insecure resource 'http://…'. This request has been blocked.
That is mixed content, and the fix is different — see telling them apart.
Two ways to survive a strict host
- Vendor the dependency. Most generators can bundle the library
into the output directory instead of linking a CDN — Plotly's
include_plotlyjs="directory", Bokeh'sCDN→INLINE, Vega's local build. Same-origin scripts satisfyscript-src 'self'. - Publish where the report body is not subject to the site's policy. Serving report HTML inside a sandboxed iframe lets the report keep its own dependencies while the surrounding application keeps a strict policy of its own.
The second is how Comma serves report bodies: the page runs with
allow-scripts and without allow-same-origin, so charts, filters and
drill-downs work as they do locally without the report gaining access to
the account around it (interactive HTML reports).
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.
Publish an interactive report →