From 7639f5f69da7546d6a9ea4292276b3fe5db47389 Mon Sep 17 00:00:00 2001 From: Tomas Kracmar Date: Fri, 29 May 2026 08:01:57 +0200 Subject: [PATCH] Release v1.7.18: fix Alpine.js SRI + CSP, add frontend modernization roadmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Revert @alpinejs/csp (CSP build has no support for template literals, optional chaining, or x-html β€” all used in the app template); switch back to the regular alpinejs build - Pin Alpine.js to 3.15.12 with a verified SRI hash (replaces the floating @3.x.x tag that caused the integrity check failure) - Restore 'unsafe-eval' to script-src (required by Alpine.js's new Function() expression evaluator; inline script was already eliminated in v1.7.17 so 'unsafe-inline' stays removed) - Add Phase 7.5 Frontend Modernization to ROADMAP: Vue 3 + Vite migration plan that will allow a clean CSP without unsafe-eval Co-Authored-By: Claude Sonnet 4.6 --- ROADMAP.md | 30 ++++++++++++++++++++++++++++++ VERSION | 2 +- backend/frontend/index.html | 2 +- backend/main.py | 2 +- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 4878fb2..fddc98d 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -95,6 +95,36 @@ Goal: address penetration test findings and threat model gaps. --- +## Phase 7.5: Frontend Modernization πŸ“‹ +Goal: eliminate `unsafe-eval` from the Content Security Policy by migrating from Alpine.js to a compiled frontend framework. + +Status: **Planned**. Current Alpine.js requires `unsafe-eval` because it uses `new Function()` to evaluate attribute expressions at runtime. A compiled framework evaluates all expressions at build time β€” the browser only receives static JS, making a fully clean CSP (`script-src 'self'`) possible. + +### Recommended approach: Vue 3 + Vite +Alpine.js was inspired by Vue, so the migration is largely mechanical: + +| Alpine.js | Vue 3 | +|-----------|-------| +| `x-data="aocApp()"` | ` - + diff --git a/backend/main.py b/backend/main.py index 3388423..73b3cc3 100644 --- a/backend/main.py +++ b/backend/main.py @@ -112,7 +112,7 @@ async def security_headers_middleware(request: Request, call_next): if request.url.path.startswith("/api/") or request.url.path in ("/", "/index.html"): response.headers["Content-Security-Policy"] = ( "default-src 'self'; " - "script-src 'self' cdn.jsdelivr.net alcdn.msauth.net; " + "script-src 'self' 'unsafe-eval' cdn.jsdelivr.net alcdn.msauth.net; " "style-src 'self' 'unsafe-inline'; " "connect-src 'self' https://login.microsoftonline.com; " "frame-src 'self' https://login.microsoftonline.com; "