import DOMPurify from "dompurify";
function Comment({ html }) {
const clean = DOMPurify.sanitize(html, {
ALLOWED_TAGS: ["b", "i", "em", "strong", "a", "p", "ul", "li"],
ALLOWED_ATTR: ["href"],
});
return <div dangerouslySetInnerHTML={{ __html: clean }} />;
}
Run the HTML through an allowlist sanitizer right before you insert it. DOMPurify parses the HTML with the browser's own parser. It removes everything dangerous, such as <script> tags, event attributes like onerror, and javascript: URLs. It keeps the safe tags.
Rules for using it well:
- Allow as little as possible. Use
ALLOWED_TAGSandALLOWED_ATTRto list only what your editor produces. - Sanitize last. Don't change the string after sanitizing. Joining strings or running a markdown or template step afterwards can create new dangerous HTML. If you render markdown, sanitize the HTML that the markdown library outputs.
- Sanitize where you render. Server-side cleaning on save is a good extra layer. But the check right before insertion protects you even if old or imported data is dirty.
- Keep DOMPurify updated. Researchers find bypasses, and new versions fix them.
- Ask if you need HTML at all. Plain text with
textContent, or markdown with a small allowed set, is much safer.
DOMPurify also works with Trusted Types. The RETURN_TRUSTED_TYPE option makes it return a TrustedHTML object instead of a string.
- Use an allowlist sanitizer like DOMPurify right before inserting HTML.
- DOMPurify removes scripts, event handler attributes and
javascript:URLs. - Allow only the tags and attributes your feature needs.
- Never change the HTML after sanitizing it.
- Keep the sanitizer updated, and prefer plain text when HTML isn't needed.