Bug 42800: (QA follow-up) Fix backslash breaking the shelf list script block

erm.tt built the logged_in_user_lists JS array by manually
interpolating each shelf's id/name into a JS string literal, escaped
with the TT html filter:

    id: "[% shelf.shelfnumber | html %]",
    name: "[% shelf.shelfname | html %]",

The html filter escapes <, >, &, and " -- enough to stop the
<script>-tag and </script>-breakout scenario from the original bug --
but it does not escape backslashes. A list name ending in a backslash
(e.g. "foo\") escapes the closing quote of the JS string literal,
unbalancing it and throwing a JS syntax error that breaks the whole
inline <script> block on every ERM page (including the unrelated
`const logged_in_user = ...` a few lines below), reproducing the
"broken UI" half of the original bug via a different character.

Build the id/name pairs as an actual array of hashes and JSON-encode
them with To.json(), after escaping each value with the html
vmethod. JSON encoding (via the JSON module) correctly escapes
backslashes and quotes for use inside a JS string, while keeping the
values HTML-escaped so they stay inert if ever written into the DOM
via innerHTML (as the DataTables render callback in
EHoldingsLocalTitlesFormImport.vue does).

Test plan:
1. Enable the ERMModule system preference.
2. Create a list named: backslash test \
3. Go to /cgi-bin/koha/erm/eholdings/local/titles/import (or any
   other ERM page).
   => Without this patch: the page's inline script throws a syntax
      error ("Invalid or unexpected token") and
      "logged_in_user_lists is not defined", breaking the Vue
      component.
   => With this patch: the page loads without errors and the list is
      shown correctly in the table.
4. Also verify the original bug's script-tag scenario still works:
   create a list named <script>alert("booh!");</script> and confirm
   it displays as inert text, not executing, on the same pages.

(cherry picked from commit afa208e950efae6c3a6e27c74af6d9184602b737)
Signed-off-by: Fridolin Somers <fridolin.somers@biblibre.com>
This commit is contained in:
Martin Renvoize 2026-08-04 17:10:19 +01:00 committed by Fridolin Somers
parent 24f267c2b4
commit 9ddae25e63
No known key found for this signature in database
GPG Key ID: 9A8E73E2A8B96537
1 changed files with 3 additions and 7 deletions

View File

@ -42,15 +42,11 @@
const max_allowed_packet = [% To.json(max_allowed_packet) | $raw %];
let logged_in_user_lists = [];
[% SET logged_in_user_lists_data = [] %]
[% FOR shelf IN logged_in_user.virtualshelves %]
logged_in_user_lists.push(
{
id: "[% shelf.shelfnumber | html %]",
name: "[% shelf.shelfname | html %]",
}
);
[% logged_in_user_lists_data.push( { id => shelf.shelfnumber.html, name => shelf.shelfname.html } ) %]
[% END %]
const logged_in_user_lists = [% To.json(logged_in_user_lists_data) | $raw %];
const logged_in_user = [% To.json(logged_in_user.unblessed) | $raw %];