Skip to content

[low priority] confirm_btn macro interpolates message into inline JS without tojson #55

Description

@CST-100

Summary

The confirm_btn macro in src/opal/web/templates/opalkit/_macros.html (~line 344) interpolates {{ message }}, {{ action }}, {{ method }}, and {{ redirect }} directly into single-quoted JS strings inside a double-quoted onclick attribute:

onclick="if(confirm('{{ message }}')) { ... fetch('{{ action }}', {method: '{{ method }}', ...}) ... }"

This is the same class of bug as #47 (fixed in #54): Jinja autoescaping does not protect JS-in-attribute contexts, because the HTML parser decodes ' back to ' before the JS is parsed. Any value containing a single quote breaks out of the JS string.

Why this is low priority, not a live vulnerability

Every current caller passes a literal template string or non-user-controlled data:

  • parts/detail.html:39part.internal_pn (system-generated, no quotes)
  • risks/detail.html:197, datasets/detail.html:56 — static literals

So there is no exploitable path today. The risk is latent: the first caller that interpolates a user-controlled name (e.g. message="Delete " ~ part.name ~ "?") silently introduces a stored XSS, with nothing at the macro to stop it.

Suggested fix

Route the interpolated values through | tojson, following the convention established in #54 (single-quoted onclick attribute + {{ value | tojson }}). Note the macro currently uses a double-quoted attribute with many nested single-quoted JS strings, so the quoting needs restructuring — either switch the attribute to single quotes (and tojson the literal-quote values) or use | tojson | forceescape to keep it usable inside the double-quoted attribute.

Add a rendering test alongside tests/unit/test_template_xss.py that renders a confirm_btn whose message contains ' and \ and asserts the confirm() argument JSON-round-trips.

Found while fixing #47.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions