rehype-sanitize breaks math rendering

See original GitHub issue

Initial checklist

Affected packages and versions

remark-math@5.1.0, rehype-katex@6.0.1, rehype-sanitize@5.0.0

Link to runnable example

https://codesandbox.io/s/react-markdown-debug-forked-3rbkc?file=/src/App.js

Steps to reproduce

The above sandbox link should work! code copied below for posterity.

Code:
import React from "react";
import Markdown from "react-markdown";
import rehypeKatex from "rehype-katex";
import rehypeSanitize from "rehype-sanitize";
import remarkMath from "remark-math";

import "katex/dist/katex.min.css";

const mathMarkdown = `
Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following
equation.

$$
L = \\frac{1}{2} \\rho v^2 S C_L
$$
`;

export default function App() {
  return (
    <>
      <h1>Without sanitize</h1>
      <Markdown rehypePlugins={[rehypeKatex]} remarkPlugins={[remarkMath]}>
        {mathMarkdown}
      </Markdown>
      <h1>With sanitize</h1>
      <Markdown
        rehypePlugins={[rehypeKatex, rehypeSanitize]}
        remarkPlugins={[remarkMath]}
      >
        {mathMarkdown}
      </Markdown>
    </>
  );
}

Result:

Screen Shot 2021-09-29 at 1 36 11 PM

Expected behavior

rehype-katex should still be able to correctly render math after rehype-sanitize runs. According to https://github.com/remarkjs/remark-math#security its advised to add rehype-sanitize if accepting user input. Even if safe without sanitize, I still need rehype-sanitize since I’m also using rehype-raw and rehype-autolink-headings.

Note, this breaks regardless of the order of plugins are added.

Actual behavior

Math does not correctly render.

Runtime

Other (please specify in steps to reproduce)

Package manager

yarn v1

OS

macOS

Build and bundle tools

Webpack

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
maclockardcommented, Oct 1, 2021

Awesome! thanks for you help. I’m going to make a PR adding a little snippet under security mentioning this solution

1reaction
maclockardcommented, Sep 29, 2021

After some fiddling, I found a schema for sanitize that seems to allow for katex to work:

const mathSanitizeSchema = {
  ...defaultSchema,
  attributes: {
    ...defaultSchema.attributes,
    div: [
      ...defaultSchema.attributes.div,
      ["className", "math", "math-display"]
    ],
    math: [["xmlns", "http://www.w3.org/1998/Math/MathML"], "display"],
    annotation: ["encoding"],
    span: ["className", "style"],
    svg: [
      ["xmlns", "http://www.w3.org/2000/svg"],
      "width",
      "height",
      "viewBox",
      "preserveAspectRatio"
    ],
    path: ["d"]
  },
  tagNames: [
    ...defaultSchema.tagNames,
    "math",
    "semantics",
    "annotation",
    "mrow",
    "mi",
    "mo",
    "mfrac",
    "mn",
    "msup",
    "msub",
    "svg",
    "path"
  ]
};

However, I’m unsure of the security implications of allowing some of these tags/attributes. Specifically svg, path, and allowing the attributes className and style on span.

Full sandbox + some “tests”: https://codesandbox.io/s/react-markdown-debug-forked-6k0nv?file=/src/App.js:551-1247

Copied code for posterity
import React from "react";
import Markdown from "react-markdown";
import rehypeKatex from "rehype-katex";
import rehypeRaw from "rehype-raw";
import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
import remarkMath from "remark-math";

import "katex/dist/katex.min.css";

const mathMarkdown = `
Lift($L$) can be determined by Lift Coefficient ($C_L$) like the following
equation.

$$
L = \\frac{1}{2} \\rho v^2 S C_L
$$

$$
\\sqrt{a}
$$

$$
f(\\relax{x}) = \\int_{-\\infty}^\\infty
    f(\\hat\\xi)\\,e^{2 \\pi i \\xi x}
    \\,d\\xi
$$
`;

const mathSanitizeSchema = {
  ...defaultSchema,
  attributes: {
    ...defaultSchema.attributes,
    div: [
      ...defaultSchema.attributes.div,
      ["className", "math", "math-display"]
    ],
    math: [["xmlns", "http://www.w3.org/1998/Math/MathML"], "display"],
    annotation: ["encoding"],
    span: ["className", "style"],
    svg: [
      ["xmlns", "http://www.w3.org/2000/svg"],
      "width",
      "height",
      "viewBox",
      "preserveAspectRatio"
    ],
    path: ["d"]
  },
  tagNames: [
    ...defaultSchema.tagNames,
    "math",
    "semantics",
    "annotation",
    "mrow",
    "mi",
    "mo",
    "mfrac",
    "mn",
    "msup",
    "msub",
    "svg",
    "path"
  ]
};

export default function App() {
  return (
    <>
      <h1>Without sanitize</h1>
      <Markdown rehypePlugins={[rehypeKatex]} remarkPlugins={[remarkMath]}>
        {mathMarkdown}
      </Markdown>
      <h1>With sanitize</h1>
      <Markdown
        rehypePlugins={[
          rehypeRaw,
          rehypeKatex,
          [rehypeSanitize, mathSanitizeSchema]
        ]}
        remarkPlugins={[remarkMath]}
      >
        {mathMarkdown}
      </Markdown>
    </>
  );
}

Are the above changes safe to the sanitize schema to make assuming user input? If so, I might make a PR documenting this under the security section of the README.

I’m also encountering similar needs to tweak the schema for other remark/rehype plugins, so I could also create PRs for those tweaks as well. Although, I wonder if there’s something the plugins themselves could do here in terms of modifying the schema automatically

Read more comments on GitHub >

github_iconTop Results From Across the Web

rehype/plugins.md at main - GitHub
rehype is a tool that transforms HTML with plugins. See the monorepo readme for info on what the rehype ecosystem is. This page...
Read more >
rehype-katex - unified
This package is a unified (rehype) plugin to render math. You can combine it with remark-math for math in markdown or add math-inline...
Read more >
react-markdown/changelog.md - UNPKG
107, (rendering math with KaTeX), or ... 141, [`rehype-sanitize`](https://github.com/rehypejs/rehype-sanitize). 142, too. 143. 144, <details>.
Read more >
rehype-mathjax - npm
This package is a unified (rehype) plugin to render math. You can combine it with remark-math for math in markdown or add math-inline...
Read more >
@bytemd/plugin-breaks - npm Package Health Analysis | Snyk
Learn more about @bytemd/plugin-breaks: package health score, popularity, security ... more closely: If we want to render syntax like $a+b$ to Math formula, ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found