diff --git a/report_job_log.py b/report_job_log.py index 436d07d..d589dab 100755 --- a/report_job_log.py +++ b/report_job_log.py @@ -82,7 +82,13 @@ def status_phrase(status): key = DEFAULT_STATUS if key in STATUS_PHRASES: return STATUS_PHRASES[key] - return "finished with status `" + status.strip() + "`" + # Backticks removed, not escaped: the verbatim value goes inside a code + # span in a **bold** header, and a backtick in it closes the span early -- + # the rest of the status then renders as markdown. Nothing hostile is + # expected here (`${{ job.status }}` is written by whoever wrote the + # workflow), but this repo is public and consumed by four others, and a + # branch name or matrix value could reach this argument later. + return "finished with status `" + status.strip().replace("`", "") + "`" def missing_log_note(path, phrase): diff --git a/test_report_job_log.py b/test_report_job_log.py index 0240806..4334e32 100755 --- a/test_report_job_log.py +++ b/test_report_job_log.py @@ -313,6 +313,15 @@ class TestStatusPhrase(unittest.TestCase): self.assertEqual(report_job_log.status_phrase("weird"), "finished with status `weird`") + def test_a_backtick_in_an_unknown_status_cannot_escape_the_code_span(self): + """The verbatim value sits in a code span inside a **bold** header, so + a backtick in it would close the span and let the rest render as + markdown. `${{ job.status }}` is workflow-author-controlled rather than + hostile, but this script is public and shared by four repos.""" + phrase = report_job_log.status_phrase("x` **loud** `y") + self.assertEqual(phrase, "finished with status `x **loud** y`") + self.assertEqual(phrase.count("`"), 2) + def test_default_constant_is_failed(self): """Named so that changing it is a deliberate act, not a typo.""" self.assertEqual(report_job_log.DEFAULT_STATUS, "failed")