[BUG] Security audit recommends blocking unsafe-eval in CSP without detecting Alpine.js v3 dependency — breaks reactive directives silently
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
What's Wrong?
When Claude Code's security audit/review recommends adding a Content Security Policy to a site using Alpine.js v3, the generated CSP blocks unsafe-eval. Alpine.js v3 internally uses new Function() for evaluating reactive expressions (e.g. x-text, x-show, x-bind, x-on), which requires unsafe-eval to be present in script-src. Without it, Alpine.js loads without error but all reactive directives silently stop working.
Steps to Reproduce
- Have a site using Alpine.js v3 (CDN import, e.g.
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js">) - Ask Claude Code to add security headers / CSP to the site
- Claude Code generates a CSP like:
````
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.jsdelivr.net 'nonce-xxx'; ...
- Deploy to production
- Observe: Alpine.js script loads (no 404), page renders, but ALL reactive bindings stop working:
x-textvalues are empty stringsx-showelements remain visible regardless of state- Dropdowns, drawers, language toggles — all broken
- No visible JS error in console (the error is a CSP violation logged in dev tools, easy to miss)
What Should Happen?
Claude Code should detect Alpine.js v3 (or v2) in the codebase and automatically include 'unsafe-eval' in script-src when generating CSP, or at minimum warn that blocking unsafe-eval will break Alpine.js reactivity.
Root Cause
Alpine.js v3 uses new Function(expression) to compile reactive expressions at runtime. This is a known architectural choice documented in the Alpine.js v3 migration guide. The new Function() call triggers a CSP unsafe-eval violation. The failure is completely silent in production unless the developer explicitly monitors the browser's CSP violation log.
Alpine.js v2 has the same issue for a different reason: it uses eval() in expression parsing.
Impact
- Silent regression: The site appears to deploy correctly; no build errors, no 404s, no console errors visible without inspecting DevTools Security tab
- Complete UI breakage: Every reactive component stops working — menus, toggles, forms, animations, language switchers
- Production incident: After security hardening on nuvaus.com (Alpine.js v3.14.1 CDN), the entire bilingual UI became non-functional until
'unsafe-eval'was added back (commitd4f8ea7) - Scope: Affects any project using Alpine.js v2/v3, a popular lightweight reactive library (~70k npm weekly downloads)
Workaround
Add 'unsafe-eval' to script-src in the generated CSP:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.jsdelivr.net 'unsafe-eval'; ...
Note: 'unsafe-eval' is less secure than nonce-based CSP but required for Alpine.js. A nonce-based alternative would require Alpine.js to support CSP nonces (which v3.13.5+ supports via Alpine.nonce(), but requires server-side nonce injection — complex for static sites).
Suggested Fix
When the security audit skill generates or audits a CSP:
- Detect Alpine.js: grep/search for
alpinejsin<script>tags orpackage.json - If found: include
'unsafe-eval'inscript-srcOR add a prominent warning block:
> ⚠️ Alpine.js v3 requires unsafe-eval in script-src. Blocking it will silently break all reactive directives (x-text, x-show, x-bind, x-on).
- Document Alpine.js nonce mode as an alternative for production hardening
The same pattern applies to other frameworks that use new Function() at runtime: Lit (template compilation), some Angular builds, and others.
Environment
- OS: Windows 11 Pro 10.0.26200
- Claude Code: latest
- Alpine.js: v3.14.1 (CDN)
- Site type: static (HTML + Tailwind CDN, no build step)
- Deploy: Vercel Pro
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗