diff --git a/CHANGELOG.md b/CHANGELOG.md
index 14da29a..a3f754b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,13 @@ and Recore uses semantic versioning.
## [Unreleased]
+### Fixed
+
+- The website's policy picker builds its sentence from text nodes instead of
+ markup, so a policy name read from the page is always shown as text and can
+ never run as HTML (CodeQL `js/xss-through-dom`). The documentation search
+ also escapes quotes in the result links it writes.
+
### Added
- Recore is archived on Zenodo. The README carries the DOI badge and both DOIs
diff --git a/docs/assets/site.js b/docs/assets/site.js
index 092374d..fb3dedd 100644
--- a/docs/assets/site.js
+++ b/docs/assets/site.js
@@ -553,9 +553,20 @@
b.setAttribute("aria-pressed", b.getAttribute("data-policy") === policy ? "true" : "false");
});
if (summary) {
- summary.innerHTML =
- "With " + policy + ", " + putBack + " of " + total + " go into the corrected matrix. " +
- "The other " + (total - putBack) + " stay in the states file and orthology_evidence.tsv, with the reason.";
+ // Built from nodes, not markup: the policy name is read from the
+ // page, and it goes in as text.
+ var code = function (text) {
+ var el = document.createElement("code");
+ el.textContent = text;
+ return el;
+ };
+ var count = document.createElement("b");
+ count.textContent = putBack + " of " + total;
+ summary.textContent = "";
+ summary.append(
+ "With ", code(policy), ", ", count, " go into the corrected matrix. The other " + (total - putBack) +
+ " stay in the states file and ", code("orthology_evidence.tsv"), ", with the reason."
+ );
}
}
buttons.forEach(function (b) {
@@ -599,7 +610,7 @@
var active = -1;
function escapeHtml(text) {
- return text.replace(/&/g, "&").replace(//g, ">");
+ return text.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """);
}
// Words match where a word starts, so "min" finds --min-prevalence and
@@ -669,7 +680,7 @@
var e = hit.entry;
var title = e.section ? e.page + " \u203a " + e.section : e.page;
return (
- '' + highlight(title, words) + "" +
+ '' + highlight(title, words) + "" +
highlight(snippet(e.text, words[0]), words) + ""
);
})