Kaynağa Gözat

docs: mark SEC_REVIEW F53 as fixed by F24 (193f646)

F53 noted that `categories/edit.twig` passed `decay_function` into
the Alpine `x-data` expression as `'{{ category.decay_function }}'` —
Twig's default `e('html')` escapes single quotes to `'`, which
the browser HTML-decodes before Alpine evaluates the attribute as
JavaScript, so `'` returns to a literal `'` and any apostrophe
in `decay_function` would break out of the JS string.

The F24 fix (commit 193f646), driven by the CSP-tightening work
that removed `'unsafe-inline'` / `'unsafe-eval'`, rewrote every
inline-eval Alpine pattern in the project. The categories edit
template now reads:

  <div x-data="decayPreview"
       data-decay-fn="{{ category.decay_function }}"
       data-decay-param="{{ category.decay_param }}">

`x-data="decayPreview"` is the component name only — no JS
interpolation. The value flows via an HTML data attribute (Twig
auto-escapes for HTML attribute context, no JS context to break
out of), and the Alpine component reads it via
`this.$el.dataset.decayFn` (string DOM read, never `eval`). The
component further whitelists the value:
  ds.decayFn === 'linear' ? 'linear' : 'exponential'
so even if the value drifted, only the two known enum states map.

Closing F53 for bookkeeping; the F24 work is the actual fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chiappa 3 gün önce
ebeveyn
işleme
f54d83d21e
1 değiştirilmiş dosya ile 20 ekleme ve 1 silme
  1. 20 1
      doc/SEC_REVIEW.md

+ 20 - 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 (27 fixed, 0 open), 42 sev-1 (20 fixed, 22 open).
+> **Findings rolled up:** 5 sev-3 (5 fixed, 0 open), 27 sev-2 (27 fixed, 0 open), 42 sev-1 (21 fixed, 21 open).
 
 ---
 
@@ -1750,6 +1750,25 @@
   it executes. Combined with F24 (CSP `'unsafe-inline'`), live XSS.
   Use `e('js')` for content interpolated into a JS-attribute.
 - **Severity: 1**
+- **Status:** Fixed by the F24 fix (`193f646`). When the CSP dropped
+  `'unsafe-inline'` and `'unsafe-eval'`, all inline-eval Alpine
+  patterns had to be rewritten — the categories edit template now
+  reads:
+  ```html
+  <div x-data="decayPreview"
+       data-decay-fn="{{ category.decay_function }}"
+       data-decay-param="{{ category.decay_param }}">
+  ```
+  `x-data="decayPreview"` is the component name only (no inline JS
+  interpolation), and the value flows via Twig's default `e('html')`-
+  escaped HTML data attribute. The Alpine component reads it via
+  `this.$el.dataset.decayFn` — a string DOM read, never `eval`.
+  `app.js` further whitelists the value to the known enum:
+  `ds.decayFn === 'linear' ? 'linear' : 'exponential'` — so even if
+  a value somehow drifted, only the two known states map. No
+  Alpine-side regression test (no JS-interpreted Twig escaping path
+  remains in the template), but the rewritten pattern is one of the
+  CSP-build cases the F24 work covered.
 
 ### F54 — CSRF middleware lacks `Origin` / `Referer` defence in depth
 - **File:** `ui/src/Http/CsrfMiddleware.php:30, 40-48, 62-74`