From fcd8b34135ea19c6cd4fedb24c56a8b7ea755709 Mon Sep 17 00:00:00 2001 From: Philipp Wagner Date: Mon, 26 Oct 2026 10:07:44 +0100 Subject: [PATCH] fix: resolve the open CodeQL alerts Strip HTML tags and XML comments until the text no longer changes, so that nested input cannot reassemble a tag or comment after a single pass (js/incomplete-multi-character-sanitization in website/.eleventy.js and website/scripts/validate-version-info.js). Limit the GITHUB_TOKEN of the PR compile check and the test version-XML workflow to read access (actions/missing-workflow-permissions). Claude-Session: https://claude.ai/code/session_01FJBfPYm6rCH4zD6T7bcC7Y --- .github/workflows/pr-compile-check.yml | 3 +++ .../workflows/test-publish-version-xml.yml | 4 ++++ website/.eleventy.js | 21 ++++++++++++++++--- website/scripts/validate-version-info.js | 21 ++++++++++++++++--- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr-compile-check.yml b/.github/workflows/pr-compile-check.yml index 982720f8..a1fba993 100644 --- a/.github/workflows/pr-compile-check.yml +++ b/.github/workflows/pr-compile-check.yml @@ -6,6 +6,9 @@ on: - main workflow_dispatch: +permissions: + contents: read + env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true diff --git a/.github/workflows/test-publish-version-xml.yml b/.github/workflows/test-publish-version-xml.yml index 71cd9fdd..f55ed262 100644 --- a/.github/workflows/test-publish-version-xml.yml +++ b/.github/workflows/test-publish-version-xml.yml @@ -3,6 +3,10 @@ name: TEST publish-version-xml (local only) on: workflow_dispatch: +permissions: + contents: read + issues: read + jobs: publish-version-xml: name: Publish Version Info XML via WebDAV diff --git a/website/.eleventy.js b/website/.eleventy.js index d7f2eee5..29839af1 100644 --- a/website/.eleventy.js +++ b/website/.eleventy.js @@ -32,11 +32,26 @@ const MANUAL_PAGE_ORDER = { ] }; +// Removes HTML tags until none are left, so that nested input such as +// "<script>" cannot reassemble a tag after a single pass. +function stripHtmlTags(value) { + let previous; + let current = value; + + do { + previous = current; + current = current.replace(/<[^>]+>/g, ""); + } while (current !== previous); + + return current; +} + function markdownToPlainText(value) { - return (value || "") + const withoutLinks = (value || "") .replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1") - .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1") - .replace(/<[^>]+>/g, "") + .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1"); + + return stripHtmlTags(withoutLinks) .replace(/[*_~`]/g, "") .replace(/\s+/g, " ") .trim(); diff --git a/website/scripts/validate-version-info.js b/website/scripts/validate-version-info.js index f498d254..7bbc67a3 100644 --- a/website/scripts/validate-version-info.js +++ b/website/scripts/validate-version-info.js @@ -28,14 +28,29 @@ function extractTag(xml, tagName) { return match ? match[1].trim() : null; } +// Applies the removal until nothing changes, so that nested input such as +// "-->" cannot leave a fresh comment behind after a single pass. +function removeUntilStable(value, pattern) { + let previous; + let current = value; + + do { + previous = current; + current = current.replace(pattern, ""); + } while (current !== previous); + + return current; +} + function assertWellFormedStructure(xml) { if (/&(?!amp;|lt;|gt;|quot;|apos;|#\d+;|#x[0-9a-f]+;)/i.test(xml)) { fail("the XML contains an unescaped ampersand"); } - const withoutCommentsAndDeclaration = xml - .replace(//g, "") - .replace(/<\?[\s\S]*?\?>/g, ""); + const withoutCommentsAndDeclaration = removeUntilStable( + xml, + /|<\?[\s\S]*?\?>/g + ); const tagPattern = /<\/?([A-Za-z_][\w:.-]*)(?:\s[^<>]*?)?\s*\/?>/g;