mirror of https://github.com/usememos/memos.git
feat: add DOMPurify for sanitizing HTML content in CodeBlock component
This commit is contained in:
parent
f4e23727bb
commit
383553d3c8
|
|
@ -32,6 +32,7 @@
|
|||
"cmdk": "^1.1.1",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"dayjs": "^1.11.13",
|
||||
"dompurify": "^3.2.6",
|
||||
"fuse.js": "^7.1.0",
|
||||
"highlight.js": "^11.11.1",
|
||||
"i18next": "^25.4.2",
|
||||
|
|
|
|||
|
|
@ -80,6 +80,9 @@ importers:
|
|||
dayjs:
|
||||
specifier: ^1.11.13
|
||||
version: 1.11.13
|
||||
dompurify:
|
||||
specifier: ^3.2.6
|
||||
version: 3.2.6
|
||||
fuse.js:
|
||||
specifier: ^7.1.0
|
||||
version: 7.1.0
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import copy from "copy-to-clipboard";
|
||||
import DOMPurify from "dompurify";
|
||||
import hljs from "highlight.js";
|
||||
import { CopyIcon } from "lucide-react";
|
||||
import { useEffect, useMemo } from "react";
|
||||
|
|
@ -22,12 +23,63 @@ const CodeBlock: React.FC<Props> = ({ language, content }: Props) => {
|
|||
const formatedLanguage = useMemo(() => (language || "").toLowerCase() || "text", [language]);
|
||||
|
||||
// Users can set Markdown code blocks as `__html` to render HTML directly.
|
||||
// Content is sanitized to prevent XSS attacks while preserving safe HTML.
|
||||
if (formatedLanguage === SpecialLanguage.HTML) {
|
||||
const sanitizedHTML = DOMPurify.sanitize(content, {
|
||||
// Allow common safe HTML tags and attributes
|
||||
ALLOWED_TAGS: [
|
||||
"div",
|
||||
"span",
|
||||
"p",
|
||||
"br",
|
||||
"strong",
|
||||
"b",
|
||||
"em",
|
||||
"i",
|
||||
"u",
|
||||
"s",
|
||||
"strike",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
"blockquote",
|
||||
"code",
|
||||
"pre",
|
||||
"ul",
|
||||
"ol",
|
||||
"li",
|
||||
"dl",
|
||||
"dt",
|
||||
"dd",
|
||||
"table",
|
||||
"thead",
|
||||
"tbody",
|
||||
"tr",
|
||||
"th",
|
||||
"td",
|
||||
"a",
|
||||
"img",
|
||||
"figure",
|
||||
"figcaption",
|
||||
"hr",
|
||||
"small",
|
||||
"sup",
|
||||
"sub",
|
||||
],
|
||||
ALLOWED_ATTR: "href title alt src width height class id style target rel colspan rowspan".split(" "),
|
||||
// Forbid dangerous attributes and tags
|
||||
FORBID_ATTR: "onerror onload onclick onmouseover onfocus onblur onchange".split(" "),
|
||||
FORBID_TAGS: "script iframe object embed form input button".split(" "),
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
className="w-full overflow-auto my-2!"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: content,
|
||||
__html: sanitizedHTML,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue