fix(csp): ship the interface strings as a JSON data block, not an inline script

base.html.j2 set window.I18N from an executable inline <script>. A host
CSP can only allow an inline script by hash or by 'unsafe-inline', and this
script's content changes with every language, so no hash can cover it.
Infinito.Nexus serves the dashboard with a hash-based script-src-elem
whenever its logout feature is off, and there the script was blocked:
every page logged "Executing inline script violates the following Content
Security Policy directive 'script-src-elem ...'" and window.I18N stayed
undefined.

The strings now ship as <script id="i18n" type="application/json">, which
the browser does not execute and CSP does not govern; modal.js parses the
block before its first use. tojson escapes <, > and &, so a string that
contains "</script>" cannot end the block early.

Integration tests require that a page ships no executable inline script
and that a catalogue string containing "</script>" survives the round trip
through the block.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-11 23:22:11 +02:00
parent f76794df78
commit 2400cc2ea1
3 changed files with 36 additions and 1 deletions

View File

@@ -71,7 +71,7 @@
</div>
<!-- Include modal -->
{% include "moduls/modal.html.j2" %}
<script>window.I18N = {{ ui_strings | tojson }};</script>
<script id="i18n" type="application/json">{{ ui_strings | tojson }}</script>
{% for name in [
'modal',
'navigation',