gout

A static git page generator
git clone https://git.bracken.jp/gout.git
Log | Files | Refs | README | LICENSE

commit 2ed590a4100e6c6ecb4ae72dbed322774f85baf0
parent c28430201687c4c4e4dc0ddb049ae72d47acb741
Author: Chris Bracken <chris@bracken.jp>
Date:   Sat,  6 Jun 2026 14:42:13 +0900

writer/html: fix XSS/HTML injection in me_url

Escapes the me_url using print_xml_encoded before printing to link
rel=me tag to prevent arbitrary HTML/JavaScript injection.

Diffstat:
Msrc/writer/html/repo_index.c | 4+++-
Msrc/writer/html/repo_index_tests.c | 25+++++++++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/writer/html/repo_index.c b/src/writer/html/repo_index.c @@ -47,7 +47,9 @@ void html_repoindex_begin(HtmlRepoIndex* index) { "<link rel=\"icon\" type=\"image/png\" href=\"favicon.png\" />\n" "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />\n"); if (index->me_url) { - fprintf(out, "<link rel=\"me\" href=\"%s\" />\n", index->me_url); + fprintf(out, "<link rel=\"me\" href=\""); + print_xml_encoded(out, index->me_url); + fprintf(out, "\" />\n"); } fprintf( out, diff --git a/src/writer/html/repo_index_tests.c b/src/writer/html/repo_index_tests.c @@ -65,3 +65,28 @@ UTEST(html_repo_index, multiple) { free(buf); } + +UTEST(html_repo_index, escaping) { + char* buf = NULL; + size_t size = 0; + FILE* out = open_memstream(&buf, &size); + + HtmlRepoIndex* index = html_repoindex_create(out); + ASSERT_NE(NULL, index); + html_repoindex_set_me_url( + index, "https://me.example.com/?a=1&b=2\" onclick=\"alert(1)"); + + html_repoindex_begin(index); + html_repoindex_end(index); + html_repoindex_free(index); + fclose(out); + + ASSERT_NE(NULL, buf); + + // Verify that characters like & and " are escaped, and not written literally. + EXPECT_TRUE(strstr(buf, + "href=\"https://me.example.com/?a=1&amp;b=2&quot; " + "onclick=&quot;alert(1)\"") != NULL); + + free(buf); +}