Parcourir la source

docs: mark SEC_REVIEW F24 as fixed in 193f646

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chiappa il y a 4 jours
Parent
commit
921e17a693
1 fichiers modifiés avec 34 ajouts et 1 suppressions
  1. 34 1
      doc/SEC_REVIEW.md

+ 34 - 1
doc/SEC_REVIEW.md

@@ -11,7 +11,7 @@
 >
 > Each finding is referenced as **F<N>** for later citation.
 >
-> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (14 fixed, 13 open), 42 sev-1.
+> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (15 fixed, 12 open), 42 sev-1.
 
 ---
 
@@ -837,6 +837,39 @@
   exploitable without strict CSP. Migrating to nonces or hashed
   scripts and packaging Alpine-with-CSP-build would close the gap.
 - **Severity: 2**
+- **Status:** Fixed. `script-src` is now `'self' 'nonce-…'` only —
+  `'unsafe-inline'` and `'unsafe-eval'` are gone. Two changes close it:
+  1. **Per-request CSP nonce.** `App\Http\CspMiddleware` mints a 16-byte
+     URL-safe nonce per request, exposes it on the request attribute and
+     as the Twig `csp_nonce` global, and stamps a fresh
+     `Content-Security-Policy: …; script-src 'self' 'nonce-…'; …` header
+     on the response. The static CSP block is removed from
+     `ui/docker/Caddyfile` because the nonce changes per response and
+     Caddy can't see that. The only inline `<script>` left in the
+     codebase — the FOUC dark-mode preloader in
+     `ui/resources/views/layout.twig` — carries `nonce="{{ csp_nonce }}"`.
+  2. **Alpine.js CSP build.** Switched `ui/package.json` from `alpinejs`
+     to `@alpinejs/csp`, which never calls `Function()` and so does not
+     need `'unsafe-eval'`. The CSP build forbids inline expressions in
+     `x-data` / `x-on:` / `x-show` / `x-bind`, so every component lives
+     in `ui/resources/js/app.js` registered via `Alpine.data(name, …)`
+     (toggle, rowExpander, kindSwitcher, submitGuard, dangerousAction,
+     loginForm, decayPreview, policyPreview, policyScoreDistribution,
+     scoreOverTime, rawTokenCopy). Initial values are read from
+     `data-*` attributes on the root element, not interpolated into
+     attribute expressions. The audit-page datetime-local helper and
+     three previously per-page inline `<script>` blocks (categories,
+     ips/detail, policies) are inlined into `app.js`.
+  Regression tests:
+  - `ui/tests/Unit/Http/CspMiddlewareTest.php` covers nonce uniqueness,
+    URL-safe alphabet, the `script-src` + `frame-ancestors` shape, and
+    middleware integration.
+  - `ui/tests/Integration/App/CspHeaderTest.php` boots the full Slim
+    app and asserts: every response carries CSP, the layout
+    `<script nonce>` value matches the response header's
+    `'nonce-…'`, nonces rotate across requests, and no inline DOM
+    event handlers or `x-data="{…}"` object literals leak into the
+    rendered HTML.
 
 ### F25 — Trusted-proxy XFF rewrite + `private_ranges` may allow `/internal/*` bypass
 - **Files:** `api/docker/Caddyfile:7-11, 50-62`,