KaTeX 安全模型解析从输出净化到 untrusted 输入的信任边界控制【免费下载链接】KaTeXFast math typesetting for the web.项目地址: https://gitcode.com/GitHub_Trending/ka/KaTeXKaTeX 在浏览器与服务端将 LaTeX 渲染为 HTML 与 MathML 时默认不会把数学表达式当作可执行代码处理其生成的 HTML 在理论上不会携带script或其它可注入的执行代码。但面向不可信用户输入时仅靠“默认安全”并不够你需要理解maxSize、maxExpand、trust这三道防线各自的作用并配合输出净化与错误信息的转义处理才能搭建一套完整、可审计的渲染安全策略。本文以 docs/security.md 为核心骨架结合仓库源码src/Settings.ts、src/utils.ts、src/MacroExpander.ts 等逐层拆解 KaTeX 的安全模型并给出可直接落地的配置示例与测试依据。安全模型的根基输出本身不是可执行代码KaTeX 的核心安全前提是由 KaTeX 生成的 HTML 应该是安全的不包含script或其它代码注入攻击面。这一承诺来自其渲染架构——KaTeX 将 LaTeX 解析为语法树parse tree再通过 buildHTML.ts 与 buildMathML.ts 将其转换为受控的 HTML/MathML 节点domTree.ts、mathMLTree.ts整个过程不会把原始输入直接拼接到 HTML 字符串中。不过docs/security.md也明确提醒这只是一个“should”级别的保证因此在实际产品中对最终 HTML 做一次净化sanitize仍然是良好实践。难点在于KaTeX 输出中包含了相当丰富的标签与属性——例如行内样式style、span/svg/math等元素——所以净化白名单必须足够宽松需要包含 SVG 相关标签与属性如svg、path、viewBox、fill、stroke、xmlns等因为 KaTeX 的 stretchy 符号、根号、可伸缩分隔符等都依赖内联 SVG见 stretchy.ts、svgGeometry.ts需要包含 MathML 相关标签与属性如math、mrow、mfrac、msup、semantics、annotation等因为在默认输出模式下 KaTeX 会同时输出 HTML 与 MathMLhtmlAndMathmlMathML 用于屏幕阅读器等无障碍场景行内style属性是渲染尺寸、颜色、定位的关键也必须在白名单内。也就是说白名单过滤策略比黑名单更可靠但白名单必须覆盖 KaTeX 实际生成的整组标签过于严苛的过滤器反而会破坏渲染结果。如果你需要为 KaTeX 输出做服务端或前端净化建议以仓库测试test/katex-spec.ts、test/mathml-spec.ts实际生成的 DOM 结构为基准来校准白名单。面向不可信输入的三个核心安全选项docs/security.md指出KaTeX 提供了一系列选项对“不可信输入”进行更细粒度的安全控制其中最重要的三个是maxSize、maxExpand与trust。它们都通过katex.render/katex.renderToString的最后一个 options 参数传入完整的选项说明见 docs/options.md。在源码层面这些选项统一在 src/Settings.ts 的SETTINGS_SCHEMA中声明类型、默认值与 CLI 映射并在Settings构造函数中完成默认值归并。maxSize限制尺寸防止“视觉攻击”katex.renderToString(\\rule{500em}{500em}, { maxSize: 10, // 所有用户指定尺寸被限制在 10em 以内 });作用将用户指定的所有尺寸例如\rule{500em}{500em}中的500em统一封顶到maxSizeem否则元素和间距可以任意大。默认值Infinity不限制。源码依据SETTINGS_SCHEMA中maxSize的声明为default: Infinity且带处理器processor: (s) Math.max(0, s)即传入负值会被钳制为 0src/Settings.ts。CLI 对应--max-size n参数经parseInt解析。适用场景主要防御的是“视觉公害”visual affront——例如超大尺寸的\rule撑爆页面布局、拖垮浏览器渲染。它不解决脚本注入但能让恶意输入在视觉层面受到约束。maxExpand限制宏展开次数阻断无限循环攻击katex.renderToString(untrustedTex, { maxExpand: 1000, // 默认值宏展开计数上限 });作用限制宏展开macro expansion的总次数防止形如\def\loop{\loop}之类的自引用宏造成无限循环DoS 类攻击。\edef等完全展开过程会统计所有展开的 token。默认值1000设为Infinity时宏展开器会像 LaTeX 一样尝试完全展开不推荐用于不可信输入。源码依据在 src/MacroExpander.ts 中countExpansion(amount)每次累加expansionCount一旦超过settings.maxExpand就抛出ParseError错误信息为Too many expansions: infinite loop or need to increase maxExpand setting。SETTINGS_SCHEMA中maxExpand的处理器同样为Math.max(0, n)src/Settings.ts。CLI 对应--max-expand n且支持字面量Infinity。注意点宏展开计数与宏“定义”本身的复杂性相关正常数学表达式通常远达不到 1000 次若你的合法输入中大量使用自定义宏嵌套才需要谨慎上调该值——上调幅度越大面对恶意输入时的暴露面也越大。trust控制可能加载外部资源或改写 HTML 属性的命令trust是三者中最精细、也是最能体现 KaTeX 安全设计的选项。默认值为false即不信任输入任何可能造成不良行为的命令如\includegraphics会被拦截并按errorColor渲染为错误提示。当设为true时则信任输入放行所有这类命令。// 完全信任放行 \url、\href、\includegraphics、\htmlClass 等全部命令 katex.renderToString(tex, { trust: true }); // 完全不信任默认 katex.renderToString(tex, { trust: false });为什么需要 trust这类命令要么会加载外部资源\includegraphics引入图片、\url/\href生成链接要么会直接修改 HTML 属性\htmlClass、\htmlId、\htmlStyle、\htmlData因此并不总是安全。从源码结构看Settings.isTrusted(context)src/Settings.ts是这些命令的统一把关入口命令解析阶段会携带上下文信息调用它src/functions/includegraphics.ts\includegraphics在 handler 中构造{command: \\includegraphics, url: src}并调用isTrusted不通过则parser.formatUnsupportedCmd(\\includegraphics)src/functions/href.ts\href与\url同样以{command, url}上下文校验src/functions/html.ts\htmlClass、\htmlId、\htmlStyle、\htmlData按各自上下文对象class、id、style、attributes统一校验。trust的函数形式可以传入handler(context)自定义放行策略。context是包含command字段的对象具体形状如下完整列表见 docs/options.mdcontext 对象含义{command: \\url, url, protocol}链接命令protocol为小写协议名如http、https相对链接为_relative{command: \\href, url, protocol}同上的带文本超链接{command: \\includegraphics, url, protocol}图片命令{command: \\htmlClass, class}为内容附加 CSS 类{command: \\htmlId, id}为内容附加 id{command: \\htmlStyle, style}为内容附加内联样式{command: \\htmlData, attributes}为内容附加>// 禁止某个特定命令 trust: (context) context.command ! \\includegraphics // 只允许 \url trust: (context) context.command \\url // 允许多个特定命令 trust: (context) [\\url, \\href].includes(context.command) // 只允许 http 协议 trust: (context) context.protocol http // 只允许 http / https / 相对链接 trust: (context) [http, https, _relative].includes(context.protocol) // 放行所有命令但禁止 file 协议 trust: (context) context.protocol ! file // 组合策略只允许 \url 和 \href 使用 http/https/相对链接 trust: (context) [\\url, \\href].includes(context.command) [http, https, _relative].includes(context.protocol)错误信息中的 LaTeX 源码必须转义再输出docs/security.md特别强调了一处容易被忽略的安全细节KaTeX 抛出的错误信息可能包含未转义的 LaTeX 源码。当throwOnError未设为false时katex.render与katex.renderToString对无效或不支持的 LaTeX 会抛出katex.ParseError类型的异常其message中会带上部分原始 LaTeX 源码。如果直接把e.message或原始texString拼进 HTML/DOM一旦 LaTeX 源码本身是不可信输入就会产生script注入面。正确做法是先对、、做 HTML 转义amp;、lt;、gt;docs/error.md 给出了完整的参考实现try { var html katex.renderToString(texString); // span classkatex.../span } catch (e) { if (e instanceof katex.ParseError) { // KaTeX 无法解析该表达式 html (Error in LaTeX texString : e.message) .replace(//g, amp;).replace(//g, lt;).replace(//g, gt;); } else { throw e; // 其它类型的错误照常抛出 } }如果不做转义攻击者构造包含script标签的 LaTeX 字符串并触发解析错误就能借错误渲染通道完成注入——这正是“输出净化”之外的第二条防线务必与前述三个安全选项同时落实。若不想手写 try/catch也可以设置throwOnError: false让 KaTeX 内置地把 LaTeX 源码渲染为带悬停错误提示的文本颜色由errorColor控制但此时仍需保证承载该文本的 DOM 插入点是安全的。纵深防御实践清单综合docs/security.md、docs/options.md 与 docs/error.md面向不可信 LaTeX 输入的安全渲染建议按以下顺序落地输入侧设置maxSize如10封顶视觉尺寸保留maxExpand默认值1000阻断无限宏展开攻击。信任侧保持trust: false默认按业务需要仅通过函数形式放行必需的\url/\href/\includegraphics/\html*命令并叠加协议白名单http、https、_relative充分利用protocolFromUrl对实体编码冒号与非法 scheme 的拒绝能力。错误侧捕获katex.ParseError对e.message与原始输入中的、、做转义后再渲染或使用throwOnError: false的内置渲染行为。输出侧对最终生成的 HTML 做白名单式净化白名单需覆盖 KaTeX 使用的 SVG、MathML 标签/属性与行内style避免过度裁剪破坏渲染。回顾与复测仓库测试test/errors-spec.ts、test/katex-spec.ts覆盖了大量错误路径与边界输入可作为你自建回归用例的起点。漏洞上报流程如果你在 KaTeX 中发现了潜在安全问题docs/security.md约定如下流程请私下上报而非公开讨论通过 GitHub Security Advisory 或邮件联系维护团队维护团队会评估漏洞必要时发布修复与安全公告并会在报告中致谢同时邀请你参与修复方案与评估在修复发布之前请不要公开披露该漏洞。【免费下载链接】KaTeXFast math typesetting for the web.项目地址: https://gitcode.com/GitHub_Trending/ka/KaTeX创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考