#21: add explicit DOMPurify HTML sanitizer test suite and refine remote image blocker
This commit is contained in:
1 parent
1707ade6da
commit
86aad5087b
2 files changed
+65
-21
No files matched your search
@@ -5,28 +5,36 @@ import DOMPurify from "dompurify";
|
||||
* Strips scripts, dangerous attributes, and executable elements while keeping layout.
|
||||
*/
|
||||
export function sanitizeEmailHtml(rawHtml: string): string {
|
||||
if (typeof window === "undefined") {
|
||||
// SSR fallback: basic strip of script tags
|
||||
return rawHtml.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "");
|
||||
if (!rawHtml) return "";
|
||||
|
||||
// Base sanitization stripping dangerous tags and inline event handlers
|
||||
let cleaned = rawHtml
|
||||
.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, "")
|
||||
.replace(/<iframe\b[^<]*(?:(?!<\/iframe>)<[^<]*)*<\/iframe>/gi, "")
|
||||
.replace(/<object\b[^<]*(?:(?!<\/object>)<[^<]*)*<\/object>/gi, "")
|
||||
.replace(/<embed\b[^<]*(?:(?!<\/embed>)<[^<]*)*<\/embed>/gi, "")
|
||||
.replace(/\s*on\w+\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+)/gi, "");
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
cleaned = DOMPurify.sanitize(cleaned, {
|
||||
ALLOWED_TAGS: [
|
||||
"a", "b", "blockquote", "br", "caption", "code", "div", "em", "h1", "h2", "h3",
|
||||
"h4", "h5", "h6", "hr", "i", "img", "li", "ol", "p", "pre", "span", "strong",
|
||||
"table", "tbody", "td", "tfoot", "th", "thead", "tr", "u", "ul", "style", "font",
|
||||
"sub", "sup"
|
||||
],
|
||||
ALLOWED_ATTR: [
|
||||
"align", "alt", "bgcolor", "border", "cellpadding", "cellspacing", "cite",
|
||||
"class", "color", "colspan", "dir", "height", "href", "id", "lang", "rowspan",
|
||||
"src", "style", "title", "width", "target", "rel", "data-blocked-src"
|
||||
],
|
||||
ALLOW_DATA_ATTR: true,
|
||||
FORBID_TAGS: ["script", "iframe", "object", "embed", "form", "input", "button"],
|
||||
FORBID_ATTR: ["onerror", "onload", "onclick", "onmouseover", "onfocus"],
|
||||
});
|
||||
}
|
||||
|
||||
return DOMPurify.sanitize(rawHtml, {
|
||||
ALLOWED_TAGS: [
|
||||
"a", "b", "blockquote", "br", "caption", "code", "div", "em", "h1", "h2", "h3",
|
||||
"h4", "h5", "h6", "hr", "i", "img", "li", "ol", "p", "pre", "span", "strong",
|
||||
"table", "tbody", "td", "tfoot", "th", "thead", "tr", "u", "ul", "style", "font",
|
||||
"sub", "sup"
|
||||
],
|
||||
ALLOWED_ATTR: [
|
||||
"align", "alt", "bgcolor", "border", "cellpadding", "cellspacing", "cite",
|
||||
"class", "color", "colspan", "dir", "height", "href", "id", "lang", "rowspan",
|
||||
"src", "style", "title", "width", "target", "rel", "data-blocked-src"
|
||||
],
|
||||
ALLOW_DATA_ATTR: true,
|
||||
ADD_ATTR: ["target"],
|
||||
FORBID_TAGS: ["script", "iframe", "object", "embed", "form", "input", "button"],
|
||||
FORBID_ATTR: ["onerror", "onload", "onclick", "onmouseover", "onfocus"],
|
||||
});
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +44,7 @@ export function sanitizeEmailHtml(rawHtml: string): string {
|
||||
export function blockRemoteImages(html: string): string {
|
||||
if (!html) return "";
|
||||
return html
|
||||
.replace(/(<img[^>]+)src\s*=\s*("|')https?:[^"']*\2/gi, "$1data-blocked-src=$2$2")
|
||||
.replace(/(<img\b[^>]*?\b)src\s*=\s*("|')(https?:[^"']*)\2/gi, "$1data-blocked-src=$2$3$2")
|
||||
.replace(/(<[^>]+)background\s*=\s*("|')https?:[^"']*\2/gi, "$1")
|
||||
.replace(/url\(\s*['"]?https?:[^)]*\)/gi, "none");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user