fix: escape KaTeX render-error fallback to prevent XSS via {@html} (#26718)

KatexRenderer rendered the raw math source through {@html} whenever renderToString threw. throwOnError only suppresses KaTeX ParseError, so a RangeError (maximum call stack size exceeded, reachable with deeply-nested brace input) escaped into the catch and re-exposed the unescaped source. Because the math tokenizer captures everything between the delimiters verbatim, that source can carry an HTML/JS payload which then executed in the viewer's browser on the application origin, a stored, cross-user XSS reachable through normal chat/channel/shared-chat rendering. Escape the fallback so the source is shown as text and is never injected as HTML. Valid math is unaffected, it still renders through the success path.

Co-authored-by: maxntv <maxntv@users.noreply.github.com>
This commit is contained in:
Classic298
2026-07-27 07:36:41 +02:00
committed by GitHub
parent 067cf31f40
commit bc600d3f08
@@ -38,7 +38,11 @@
try {
renderedHTML = renderToString(content, { displayMode, throwOnError: false });
} catch {
renderedHTML = content;
// throwOnError only suppresses ParseError; RangeError on deep nesting escapes, so escape the fallback (never {@html} raw source)
renderedHTML = content
.replaceAll('&', '&amp;')
.replaceAll('<', '&lt;')
.replaceAll('>', '&gt;');
}
}
</script>