Skip to content

fix(reports): escape test titles in the HTML report - #1250

Merged
Chemaclass merged 1 commit into
mainfrom
fix/html-report-escaping
Aug 14, 2026
Merged

fix(reports): escape test titles in the HTML report#1250
Chemaclass merged 1 commit into
mainfrom
fix/html-report-escaping

Conversation

@Chemaclass

Copy link
Copy Markdown
Member

🤔 Background

Related #1249

src/reports/html.sh had no escaping at all. A test title is user text — bashunit::set_test_title takes anything, and a data provider interpolates values into it — and it went straight into the markup:

<td><script>alert(1)</script> & <b>bold</b></td>

A < corrupts the table, a bare & is invalid entity syntax, and a script tag runs in whoever opens the report — for a CI artifact, a browser. Every other writer escapes (JUnit, JSON, Markdown, GHA); this was the only one that did not.

Same cause, second defect: rows were joined into a temp file with | and split back on it, so a title carrying one shifted every column and emitted class="after" — a CSS class matching no rule, so the row silently lost its status colour.

💡 Changes

  • Separate the fields with US (0x1f) instead of |
  • Escape &, <, > and " in one awk pass over the collected rows — one fork per report, not per test
  • Five tests: markup neutralised, & escaped, columns stay aligned, the title still reads as written, and a plain title is untouched so the escaping is not over-eager

awk rather than ${var//&/&amp;} for the reason already recorded in #1096: a bare & in a bash replacement means "the matched text" from 5.2 on while staying literal on 3.2. The same rule applies to gsub, hence \\&, and the separator reaches awk as a byte rather than \x1f, which is not POSIX awk (#1098). This is the approach src/coverage/html_file.sh already uses for the coverage pages.

src/reports/html.sh had no escaping at all. A title is user text --
set_test_title takes anything and a data provider interpolates values into it
-- so it went straight into the table: a `<` corrupted it, a bare `&` was
invalid entity syntax, and `<script>` ran in whoever opened the report, which
for a CI artifact is a browser. Every other writer escapes; this was the one
that did not.

Rows were also joined into a temp file with `|` and split back on it, so a
title carrying one shifted every column and produced class="<fragment>", a CSS
class matching no rule, and the row lost its colour.

Separate the fields with US (0x1f) and escape & < > " in one awk pass.

awk rather than ${var//&/&amp;}: a bare `&` in a bash replacement means "the
matched text" from 5.2 on while staying literal on 3.2 (#1096). The same rule
applies to gsub, hence \\&. The separator is passed in as a byte rather than
written \x1f, which is not POSIX awk (#1098). This is the approach
src/coverage/html_file.sh already uses for the coverage pages.

Closes #1249
@Chemaclass Chemaclass added the bug Something isn't working label Aug 14, 2026
@Chemaclass Chemaclass self-assigned this Aug 14, 2026
@Chemaclass
Chemaclass merged commit 0aa6630 into main Aug 14, 2026
37 checks passed
@Chemaclass
Chemaclass deleted the fix/html-report-escaping branch August 14, 2026 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant