v1.7.13: switch Alpine.js to CSP build, remove unsafe-eval from CSP
This commit is contained in:
34
RELEASE_NOTES_v1.7.13.md
Normal file
34
RELEASE_NOTES_v1.7.13.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# AOC v1.7.13 Release Notes
|
||||||
|
|
||||||
|
**Release Date:** 2026-04-27
|
||||||
|
|
||||||
|
## Security Hardening: Alpine.js CSP Build
|
||||||
|
|
||||||
|
This release removes `unsafe-eval` from the Content-Security-Policy by switching the frontend to Alpine.js's CSP-compatible build.
|
||||||
|
|
||||||
|
### Changes
|
||||||
|
|
||||||
|
- **Frontend:** Switched from `alpinejs@3.x.x/dist/cdn.min.js` to `alpinejs@3.x.x/dist/csp.min.js`
|
||||||
|
- **Frontend:** Added explicit `Alpine.start()` call on `DOMContentLoaded` (required by CSP build)
|
||||||
|
- **Backend CSP:** Removed `'unsafe-eval'` from `script-src` directive
|
||||||
|
|
||||||
|
### Why this matters
|
||||||
|
|
||||||
|
The previous v1.7.11–1.7.12 releases included `'unsafe-eval'` in the CSP because the standard Alpine.js CDN build uses `new Function()` internally for reactive expression evaluation. The CSP build eliminates this requirement, further hardening the application against XSS and injection attacks.
|
||||||
|
|
||||||
|
### Compatibility
|
||||||
|
|
||||||
|
All existing Alpine.js directives (`x-data`, `x-init`, `x-show`, `x-text`, `x-for`, `x-if`, `x-model`, event handlers) continue to work unchanged. The CSP build uses a safe expression evaluator that produces identical behavior without `eval`/`new Function`.
|
||||||
|
|
||||||
|
## Files Changed
|
||||||
|
|
||||||
|
| File | Change |
|
||||||
|
|------|--------|
|
||||||
|
| `backend/frontend/index.html` | Alpine.js src → `csp.min.js`; added `Alpine.start()` |
|
||||||
|
| `backend/main.py` | Removed `'unsafe-eval'` from `script-src` CSP |
|
||||||
|
| `VERSION` | Bumped to 1.7.13 |
|
||||||
|
|
||||||
|
## Test Results
|
||||||
|
|
||||||
|
- **80/80 pytest tests passing**
|
||||||
|
- Ruff lint/format clean
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Admin Operations Center</title>
|
<title>Admin Operations Center</title>
|
||||||
<link rel="stylesheet" href="/style.css?v=15" />
|
<link rel="stylesheet" href="/style.css?v=15" />
|
||||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/csp@3.x.x/dist/cdn.min.js"></script>
|
||||||
<script src="https://alcdn.msauth.net/browser/2.37.0/js/msal-browser.min.js" crossorigin="anonymous"></script>
|
<script src="https://alcdn.msauth.net/browser/2.37.0/js/msal-browser.min.js" crossorigin="anonymous"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -1274,5 +1274,13 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<script>
|
||||||
|
// Alpine CSP build requires explicit start
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
if (window.Alpine && typeof window.Alpine.start === 'function') {
|
||||||
|
window.Alpine.start();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ async def security_headers_middleware(request: Request, call_next):
|
|||||||
if request.url.path.startswith("/api/") or request.url.path in ("/", "/index.html"):
|
if request.url.path.startswith("/api/") or request.url.path in ("/", "/index.html"):
|
||||||
response.headers["Content-Security-Policy"] = (
|
response.headers["Content-Security-Policy"] = (
|
||||||
"default-src 'self'; "
|
"default-src 'self'; "
|
||||||
"script-src 'self' 'unsafe-inline' 'unsafe-eval' cdn.jsdelivr.net alcdn.msauth.net; "
|
"script-src 'self' 'unsafe-inline' cdn.jsdelivr.net alcdn.msauth.net; "
|
||||||
"style-src 'self' 'unsafe-inline'; "
|
"style-src 'self' 'unsafe-inline'; "
|
||||||
"connect-src 'self' https://login.microsoftonline.com; "
|
"connect-src 'self' https://login.microsoftonline.com; "
|
||||||
"frame-src 'self' https://login.microsoftonline.com; "
|
"frame-src 'self' https://login.microsoftonline.com; "
|
||||||
|
|||||||
Reference in New Issue
Block a user