|
1 | 1 | import { sanitizeUrl } from "./urlValidation"; |
| 2 | +import DOMPurify from "dompurify"; |
2 | 3 |
|
3 | 4 | const sanitizeRepeated = (text: string, pattern: RegExp, replacement: string): string => { |
4 | 5 | let result = text; |
@@ -27,29 +28,25 @@ export const sanitizeMarkdown = (markdown: string): string => { |
27 | 28 | return `[${text}](${sanitizedUrl})`; |
28 | 29 | }); |
29 | 30 |
|
30 | | - sanitized = sanitizeRepeated(sanitized, /<script[^>]*>.*?<\/script>/gis, ""); |
31 | | - sanitized = sanitizeRepeated(sanitized, /<iframe[^>]*>.*?<\/iframe>/gis, ""); |
32 | | - sanitized = sanitizeRepeated(sanitized, /<object[^>]*>.*?<\/object>/gis, ""); |
33 | | - sanitized = sanitizeRepeated(sanitized, /<embed[^>]*\/?>/gi, ""); |
34 | | - sanitized = sanitizeRepeated(sanitized, /<form[^>]*>.*?<\/form>/gis, ""); |
35 | | - sanitized = sanitizeRepeated(sanitized, /<input[^>]*\/?>/gi, ""); |
36 | | - sanitized = sanitizeRepeated(sanitized, /<button[^>]*>.*?<\/button>/gis, ""); |
37 | | - sanitized = sanitizeRepeated(sanitized, /<applet[^>]*>.*?<\/applet>/gis, ""); |
38 | | - sanitized = sanitizeRepeated(sanitized, /<audio[^>]*>.*?<\/audio>/gis, ""); |
39 | | - sanitized = sanitizeRepeated(sanitized, /<video[^>]*>.*?<\/video>/gis, ""); |
40 | | - sanitized = sanitizeRepeated(sanitized, /<svg[^>]*>.*?<\/svg>/gis, ""); |
41 | | - sanitized = sanitizeRepeated(sanitized, /<canvas[^>]*>.*?<\/canvas>/gis, ""); |
42 | | - |
43 | | - sanitized = sanitizeRepeated(sanitized, /javascript:/gi, ""); |
44 | | - sanitized = sanitizeRepeated(sanitized, /vbscript:/gi, ""); |
45 | | - |
46 | | - sanitized = sanitizeRepeated(sanitized, /on\w+\s*=/gi, ""); |
47 | | - sanitized = sanitizeRepeated(sanitized, /style\s*=/gi, ""); |
48 | | - |
49 | | - sanitized = sanitizeRepeated(sanitized, /<meta[^>]*\/?>/gi, ""); |
50 | | - sanitized = sanitizeRepeated(sanitized, /<link[^>]*\/?>/gi, ""); |
51 | | - sanitized = sanitizeRepeated(sanitized, /<base[^>]*\/?>/gi, ""); |
| 31 | + // Use DOMPurify to sanitize dangerous HTML tags and attributes |
| 32 | + sanitized = DOMPurify.sanitize(sanitized, { |
| 33 | + ALLOWED_TAGS: [ |
| 34 | + // Allow only safe tags that are valid in Markdown output; |
| 35 | + // Configure to disallow script, iframe, object, embed, form, input, button, applet, audio, video, svg, canvas, meta, link, base |
| 36 | + "b", "i", "em", "strong", "a", "p", "ul", "ol", "li", "blockquote", "code", "pre", "span", "br", "hr", "img" |
| 37 | + ], |
| 38 | + ALLOWED_ATTR: ["href", "src", "alt", "title"], // No style, no event handlers |
| 39 | + FORBID_TAGS: [ |
| 40 | + "script", "iframe", "object", "embed", "form", "input", "button", "applet", "audio", "video", "svg", "canvas", "meta", "link", "base" |
| 41 | + ], |
| 42 | + FORBID_ATTR: [ |
| 43 | + "onerror", "onload", "onclick", "style" |
| 44 | + ] |
| 45 | + }); |
52 | 46 |
|
| 47 | + // Optional: Remove encoded protocols/entities as before |
| 48 | + sanitized = sanitized.replace(/javascript:/gi, ""); |
| 49 | + sanitized = sanitized.replace(/vbscript:/gi, ""); |
53 | 50 | sanitized = sanitized.replace(/&#x[0-9a-f]+;/gi, ""); |
54 | 51 | sanitized = sanitized.replace(/&#[0-9]+;/gi, ""); |
55 | 52 |
|
|
0 commit comments