[BUG] Security audit recommends blocking unsafe-eval in CSP without detecting Alpine.js v3 dependency — breaks reactive directives silently

Resolved 💬 1 comment Opened Apr 24, 2026 by Ariel-Meneses Closed May 28, 2026

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

  1. 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">)
  2. Ask Claude Code to add security headers / CSP to the site
  3. Claude Code generates a CSP like:

``
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.jsdelivr.net 'nonce-xxx'; ...
``

  1. Deploy to production
  2. Observe: Alpine.js script loads (no 404), page renders, but ALL reactive bindings stop working:
  • x-text values are empty strings
  • x-show elements 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 (commit d4f8ea7)
  • 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:

  1. Detect Alpine.js: grep/search for alpinejs in <script> tags or package.json
  2. If found: include 'unsafe-eval' in script-src OR 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).

  1. 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

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗