Your CSP Is Probably Useless: The unsafe-inline Epidemic
Your CSP Is Probably Useless: The unsafe-inline Epidemic
Content-Security-Policy is the most important security header on the web. It's your primary defense against cross-site scripting (XSS) — the vulnerability class that has topped the OWASP Top 10 for over a decade. A properly configured CSP tells the browser exactly which scripts are allowed to execute on your page.
But here's what we found in our benchmark data: of the projects that actually set a CSP header, the majority include unsafe-inline in their script-src directive. Which means their CSP is doing almost nothing.
Projects with a CSP that includes unsafe-inline: Formbricks, Supabase, Directus, Typebot, and others. These are well-maintained projects with real security teams. They went through the effort of adding CSP — and then immediately undermined it.
What unsafe-inline actually does
A Content-Security-Policy without unsafe-inline tells the browser: "Only execute scripts loaded from approved sources. Ignore any JavaScript embedded directly in the HTML."
This is the entire point of CSP. XSS attacks work by injecting script tags or inline event handlers into your page. If the browser refuses to execute inline scripts, the injected code is dead on arrival.
When you add 'unsafe-inline' to your script-src, you're telling the browser: "Execute inline scripts too." Which means an attacker who can inject <script>stealCookies()</script> into your page has a working attack again.
A CSP with unsafe-inline is like a lock with the key taped to the door. Technically present. Functionally useless for its primary purpose.
Why projects add it
Nobody adds unsafe-inline because they want weaker security. They add it because things break without it, and the breakage is immediate and visible.
Third-party scripts
Google Analytics, Intercom, Segment, HubSpot — most third-party services inject inline scripts. Their installation instructions literally tell you to paste a <script> tag into your HTML. Without unsafe-inline, these scripts are blocked and the service stops working.
CSS-in-JS
Libraries like styled-components, Emotion, and MUI inject <style> tags at runtime. Without unsafe-inline in style-src, your entire app renders unstyled. This is particularly common in React ecosystems where CSS-in-JS is the default styling approach.
Framework behavior
Some frameworks inject inline scripts for hydration data, environment variables, or module loading. Next.js, for example, inlines __NEXT_DATA__ as a script tag. Without special handling, removing unsafe-inline breaks hydration.
Code editors and rich text
Projects that embed Monaco (VS Code's editor), CodeMirror, or any rich-text editor often need because the editor evaluates user input as code. Typebot and similar tools fall into this category.