XSS riflesso e pagina rotta: parametri di query dentro x-data senza tojson #10

Closed
opened 2026-09-21 20:14:40 +00:00 by Adriano · 3 comments
Owner

GRAVITÀ: alta
FILE: src/frontend/flask_app/templates/measure/select_recipe.html:9-11 ; src/frontend/flask_app/templates/maker/recipe_list.html:9
COSA: recipe, lot, serial, search finiscono in un letterale JS con apici dentro x-data. Jinja scrive ', il browser lo ridecodifica prima che Alpine valuti. La CSP ha unsafe-eval. Il filtro tojson_attr esiste (app.py:122) e qui non è usato.
INPUT: /measure/select?recipe=',x:alert(document.domain),y:' esegue codice. /measure/select?lot=L'23 → SyntaxError, nessuna ricetta selezionabile finché la sessione tiene quel lotto.
VERIFICATO: test client Flask + HTMLParser → x-data decodificato = search: '',x:alert(document.domain),y:'', ; lot_number: 'L'23',.

ORIGINE: revisione fable del 21/09/2026 su ramo V3.0.0, commit 8cc5e82. Documento completo: _output/2026-09-21-TieMeasureFlow-revisione.md su Wasabi.

GRAVITÀ: alta FILE: src/frontend/flask_app/templates/measure/select_recipe.html:9-11 ; src/frontend/flask_app/templates/maker/recipe_list.html:9 COSA: `recipe`, `lot`, `serial`, `search` finiscono in un letterale JS con apici dentro `x-data`. Jinja scrive `'`, il browser lo ridecodifica prima che Alpine valuti. La CSP ha `unsafe-eval`. Il filtro `tojson_attr` esiste (app.py:122) e qui non è usato. INPUT: `/measure/select?recipe=',x:alert(document.domain),y:'` esegue codice. `/measure/select?lot=L'23` → SyntaxError, nessuna ricetta selezionabile finché la sessione tiene quel lotto. VERIFICATO: test client Flask + HTMLParser → x-data decodificato = `search: '',x:alert(document.domain),y:'',` ; `lot_number: 'L'23',`. ORIGINE: revisione fable del 21/09/2026 su ramo `V3.0.0`, commit 8cc5e82. Documento completo: `_output/2026-09-21-TieMeasureFlow-revisione.md` su Wasabi.
Adriano added the bug label 2026-09-21 20:14:40 +00:00
Adriano added the assegnata:jeeg label 2026-09-21 20:22:20 +00:00
Author
Owner

⚡ jeeg — preso in carico 2026-09-21T20:22:20Z
ramo: lavoro/jeeg · capacità: docker, gpu, systemd

⚡ jeeg — **preso in carico** 2026-09-21T20:22:20Z ramo: `lavoro/jeeg` · capacità: docker, gpu, systemd
Author
Owner

ANALISI (passo 1) — ramo lavoro/jeeg, worktree ~/lavoro/TieMeasureFlow su jeeg, lotto B2

MODIFICHE: src/frontend/flask_app/templates/measure/select_recipe.html:9-11 e templates/maker/recipe_list.html:9 — ogni dato Jinja dentro x-data passa da |tojson_attr (app.py:122) senza apici attorno. Poi grep su tutti i template: x-data= / x-init= / @click= contenenti '{{ con variabili non-_() → stessa correzione.
TEST: src/frontend/flask_app/tests — base: /tmp/claude-1000/-data-Sorgenti-AI-OS/d21ddcc5-4987-450e-a849-873258b3307a/scratchpad/t_xss.py. ?recipe=',x:alert(1),y:' → l'attributo decodificato contiene la stringa come letterale JSON, nessuna chiave x: iniettata; ?lot=L'23 → "L'23" valido.

ANALISI (passo 1) — ramo `lavoro/jeeg`, worktree `~/lavoro/TieMeasureFlow` su jeeg, lotto B2 MODIFICHE: src/frontend/flask_app/templates/measure/select_recipe.html:9-11 e templates/maker/recipe_list.html:9 — ogni dato Jinja dentro `x-data` passa da `|tojson_attr` (app.py:122) senza apici attorno. Poi grep su tutti i template: `x-data=` / `x-init=` / `@click=` contenenti `'{{` con variabili non-`_()` → stessa correzione. TEST: src/frontend/flask_app/tests — base: /tmp/claude-1000/-data-Sorgenti-AI-OS/d21ddcc5-4987-450e-a849-873258b3307a/scratchpad/t_xss.py. `?recipe=',x:alert(1),y:'` → l'attributo decodificato contiene la stringa come letterale JSON, nessuna chiave `x:` iniettata; `?lot=L'23` → `"L'23"` valido.
Author
Owner

Soluzione

ESITO: fatto
COSA: I dati Jinja dentro x-data passano da |tojson_attr (select_recipe.html, recipe_list.html). Prova originale del revisore rilanciata: il payload resta un letterale JSON ("\u0027,x:alert(...)"), ?lot=L'23 dà una pagina valida.
COMMIT (ramo lavoro/jeeg, unito su V3.0.0 a d483fa1): 51f3fe3
PROVA: uv run --extra server --extra client --extra dev pytest -q → 622 passed, 4 skipped (erano 391); visione su Python 3.13 → 16 passed (erano 8).

**Soluzione** ESITO: fatto COSA: I dati Jinja dentro `x-data` passano da `|tojson_attr` (select_recipe.html, recipe_list.html). Prova originale del revisore rilanciata: il payload resta un letterale JSON (`"\u0027,x:alert(...)"`), `?lot=L'23` dà una pagina valida. COMMIT (ramo lavoro/jeeg, unito su V3.0.0 a d483fa1): 51f3fe3 PROVA: `uv run --extra server --extra client --extra dev pytest -q` → 622 passed, 4 skipped (erano 391); visione su Python 3.13 → 16 passed (erano 8).
Adriano removed the assegnata:jeeg label 2026-09-21 21:56:13 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Adriano/TieMeasureFlow#10