fix(ui): delete prompts use data-confirm, so a quote in a name no longer runs script (#5099)

#5099 "A name containing a quote runs script when an admin clicks Delete".
Inline handlers like onclick="return confirm('Delete {{ rule.name }}?')" are
HTML-decoded before the JavaScript is parsed, so autoescaping did not stop a
name such as  x');fetch(…);//  from running.

- Every prompt (22 handlers, plus the docker prune and token revoke ones)
  is now data-confirm="…", read through dataset by one submit listener in
  base.html; nothing rendered is parsed as JavaScript.
- The remaining inline handlers take integers only (|int), and the time
  range buttons pass this.dataset.range.
- tests/test_inline_handlers.py fails on any {{ }} in an inline handler that
  is not |int, with a self-test; tests/_templates.py is the one template
  walker the template guards now share.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 14:30:13 -04:00
co-authored by Claude Opus 5.5
parent 737d699308
commit f47fc23265
28 changed files with 97 additions and 49 deletions
@@ -46,7 +46,7 @@
{% endif %}
<button class="btn btn-ghost btn-sm" style="font-size:0.78rem;"
onclick="toggleAnsibleEdit({{ idx }})">Edit</button>
onclick="toggleAnsibleEdit({{ idx|int }})">Edit</button>
<button class="btn btn-danger btn-sm" style="font-size:0.78rem;"
hx-post="/settings/ansible/sources/{{ idx }}/remove"
@@ -72,7 +72,7 @@
<div class="form-group" style="margin:0;">
<label style="font-size:0.8rem;">Type</label>
<select name="type" id="ansible-edit-type-{{ idx }}"
onchange="updateAnsibleEditFields({{ idx }})">
onchange="updateAnsibleEditFields({{ idx|int }})">
<option value="local" {% if src.type == 'local' %}selected{% endif %}>local</option>
<option value="git" {% if src.type == 'git' %}selected{% endif %}>git</option>
</select>
@@ -118,7 +118,7 @@
<div style="display:flex;gap:0.5rem;margin-top:0.75rem;">
<button type="submit" class="btn btn-sm">Save</button>
<button type="button" class="btn btn-ghost btn-sm"
onclick="toggleAnsibleEdit({{ idx }})">Cancel</button>
onclick="toggleAnsibleEdit({{ idx|int }})">Cancel</button>
</div>
</form>
</div>