From e3680643cfa78366fcccba1f059964d97b04e8c9 Mon Sep 17 00:00:00 2001 From: David Arcos Date: Sun, 4 Oct 2026 21:06:44 +0200 Subject: [PATCH 01/16] wip: add bin/check-rendered, a check on the built site bin/check-html-safety reads content/, which is the right scope: it is what an outside contributor can change. But the worst defect found in this repository lived in a template, so the content was innocent and the check returned PASS on a payload that rendered a live anchor in the sponsor grid. This check reads what Hugo built, where a defect of that class is visible wherever it lives. It parses every built page rather than grepping, because the site builds with --minify, which unquotes attributes and turns an escaped entity back into a raw character where that is inert. Incomplete and not wired into CI yet: no canary fixture, no allowlist measured against the real tree, and the acceptance test against the vulnerable template has not been run. Committed as a checkpoint. --- bin/check-rendered | 670 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 670 insertions(+) create mode 100755 bin/check-rendered diff --git a/bin/check-rendered b/bin/check-rendered new file mode 100755 index 00000000..6002ad51 --- /dev/null +++ b/bin/check-rendered @@ -0,0 +1,670 @@ +#!/usr/bin/env python3 +"""Find dangerous markup in the built site. + +bin/check-html-safety reads content/, which is what an outside contributor +can change, and it is right to stop there: layouts/, themes/, static/, bin/ +and config.toml are in CODEOWNERS. But the worst defect this project found +lived in a template. themes/pybcn_theme/layouts/partials/sponsor_summary.html +assembled the logo markup with printf and emitted it through safeHTML, so the +sponsor name and the logo URL from front matter reached the page unescaped. +The content was innocent, the template was not, and check-html-safety +returned PASS on a payload that rendered a live anchor in the sponsor grid. + +This check reads what Hugo built. A bug of that class is visible in the +output wherever it lives: content, a shortcode, a partial, the theme, a Hugo +internal template or the minifier. + +It parses every .html file under the build directory with html.parser and +reports: + + - an on* event handler attribute on any element + - a javascript:, vbscript: or data: URL in an attribute the browser loads + from or navigates to (href, src, srcset, action, formaction, poster and + the rest of URL_ATTRIBUTES), in a meta refresh, and in a url() of an + inline style + - a