Fix guide · high · csp_unsafe_eval
CSP allows 'unsafe-eval' in script-src
Your Content-Security-Policy header includes 'unsafe-eval' in script-src. JavaScript's string-as-code APIs (eval(), Function(), setTimeout('code', n), setInterval('code', n)) are permitted. Often left over from a build tool that needed it during development.
Why it matters
'unsafe-eval' doesn't directly bypass CSP — an attacker still needs to get script execution somehow first. But once they have any code-execution primitive, eval() and Function() let them assemble payloads from string concatenation that pattern-matching defences can't see. The compounding effect: many XSS-mitigation libraries assume CSP blocks eval, so their defence-in-depth weakens when eval is permitted.
The most common reason 'unsafe-eval' ends up in production CSP: a development tool (webpack's eval-source-map devtool, some templating engines, older Vue versions, some animation libraries) needed it locally, and the CSP that worked in dev got copied to production wholesale.
How to fix it
- Identify what needs eval. Search your codebase:
grep -rE "\beval\(|new Function\(" src/. Inspect each match. Most are removable (string templating that should use real templates; legacy code that should useJSON.parse).
- Switch dev tooling. webpack's
devtool: 'eval-source-map'is the most common offender. Switch tosource-maporcheap-source-map. Vue: ensure you're using the runtime-only build, not the runtime+compiler build (the compiler usesnew Function).
- Drop
'unsafe-eval'from production CSP. Validate the build still works.
If you have a third-party library that genuinely needs eval and there's no alternative: isolate it in an iframe with its own scope, OR scope the eval permission to that library's source via a separate script-src-elem / script-src-attr discipline.
Full guide: /blog/csp-bypass-vibe-coded.
Did vibecheck flag this on your app?
If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.
Run another inspection