cure53 / DOMPurify

DOMPurify - a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG. DOMPurify works with a secure default, but offers a lot of configurability and hooks. Demo:
https://cure53.de/purify
Other
13.34k stars 690 forks source link

Sanitize returns empty string when PARSER_MEDIA_TYPE: application/xhtml+xml and void tags #938

Closed lucamerighi closed 3 months ago

lucamerighi commented 3 months ago

Background & Context

Porting of this isomorphic-dompurify issue as it's happening with vanilla dompurify as well

Bug

DOMPurify.sanitize returns an empty string when ran on HTML strings containing void elements when application/xhtml+xml is set as parser media type.

Dompurify version: 3.1.0 JSDOM version: 24.0.0

Input

import { JSDOM } from "jsdom";
import DOMPurify from "dompurify";

const window = new JSDOM("").window;
const purify = DOMPurify(window);
const clean = purify.sanitize(
  `
<html lang="en">
<head>
    <title>Sample HTML5 Page</title>
</head>
<body>
    <p>Hello</p>
    <br>
</body>
</html>`,
  {
    PARSER_MEDIA_TYPE: "application/xhtml+xml",
  }
);
console.log(clean); // empty output

Given output

Empty string

Expected output

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
    <title>Sample HTML5 Page</title>
</head>
<body>
    <p>Hello</p>
    <br />
</body>
</html>

Same outcome for other void elements, such as meta or link tags. Removing the <br> in the provided input gives the correct output

cure53 commented 3 months ago

That is indeed expected behavior, as the parser rejects non-wellformed XML and simply refuses to do anything with it.

Once you change the type to text/xhtml it works again.

lucamerighi commented 3 months ago

With that parser it works, but void tags are kept as is. Is there some option to convert tags like <br> into their self closed <br /> form?

cure53 commented 3 months ago

Not sure, maybe by using a hook or a different parser. That would be out-of-scope for DOMPurify but can likely be achieved with a hook.

cure53 commented 3 months ago

Closing this for now as we don't have anything to fix on our end :slightly_smiling_face: