fix(security): bound KaTeX rendering of remote LaTeX
maxSize 10, maxExpand 100, trust false, strict ignore, and a 5000-char
cap (rendered as plain text beyond it), so a remote sender can't blow out
layout or CPU with \rule{99999em} or deep macro expansion.
Fixes #65
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -21,12 +21,31 @@ type KaTeXProps = {
|
|||||||
* inline (in its error colour) rather than throwing. The HTML returned by
|
* inline (in its error colour) rather than throwing. The HTML returned by
|
||||||
* `renderToString` is produced by our own trusted call from a fixed options
|
* `renderToString` is produced by our own trusted call from a fixed options
|
||||||
* object — it is safe to inject via `dangerouslySetInnerHTML`.
|
* object — it is safe to inject via `dangerouslySetInnerHTML`.
|
||||||
|
*
|
||||||
|
* `maxSize`/`maxExpand` cap how large a single glyph (`\\rule`, etc.) or macro
|
||||||
|
* expansion remote LaTeX can request, and `trust: false` disables commands
|
||||||
|
* that can embed arbitrary HTML/URLs (e.g. `\\includegraphics`, `\\href`) —
|
||||||
|
* without these a hostile `$$...$$` from a remote message can DoS or (via
|
||||||
|
* `trust`) inject unsafe links (Gitea #65). `strict: 'ignore'` keeps unknown-
|
||||||
|
* but-harmless LaTeX from spamming the console as before. Extremely long
|
||||||
|
* source is rendered as plain text rather than handed to KaTeX at all.
|
||||||
*/
|
*/
|
||||||
|
const MAX_LATEX_LENGTH = 5000;
|
||||||
|
|
||||||
export default function KaTeX({ latex, displayMode = false }: KaTeXProps) {
|
export default function KaTeX({ latex, displayMode = false }: KaTeXProps) {
|
||||||
|
if (latex.length > MAX_LATEX_LENGTH) {
|
||||||
|
const Plain = displayMode ? 'div' : 'span';
|
||||||
|
return <Plain>{latex}</Plain>;
|
||||||
|
}
|
||||||
|
|
||||||
const html = katex.renderToString(latex, {
|
const html = katex.renderToString(latex, {
|
||||||
displayMode,
|
displayMode,
|
||||||
throwOnError: false,
|
throwOnError: false,
|
||||||
output: 'htmlAndMathml',
|
output: 'htmlAndMathml',
|
||||||
|
maxSize: 10,
|
||||||
|
maxExpand: 100,
|
||||||
|
trust: false,
|
||||||
|
strict: 'ignore',
|
||||||
});
|
});
|
||||||
|
|
||||||
const Wrapper = displayMode ? 'div' : 'span';
|
const Wrapper = displayMode ? 'div' : 'span';
|
||||||
@@ -34,7 +53,7 @@ export default function KaTeX({ latex, displayMode = false }: KaTeXProps) {
|
|||||||
return (
|
return (
|
||||||
<Wrapper
|
<Wrapper
|
||||||
// KaTeX output is generated by our own render call (trusted-safe).
|
// KaTeX output is generated by our own render call (trusted-safe).
|
||||||
// eslint-disable-next-line react/no-danger
|
|
||||||
dangerouslySetInnerHTML={{ __html: html }}
|
dangerouslySetInnerHTML={{ __html: html }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user