Skip to content

Commit e3dc195

Browse files
Potential fix for code scanning alert no. 96: Bad HTML filtering regexp
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
1 parent 4f35c9d commit e3dc195

File tree

2 files changed

+22
-23
lines changed

2 files changed

+22
-23
lines changed

web/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@
131131
"styled-components": "^5.3.3",
132132
"subgraph-status": "^1.2.4",
133133
"viem": "^2.24.1",
134-
"wagmi": "^2.14.15"
134+
"wagmi": "^2.14.15",
135+
"dompurify": "^3.2.6",
136+
"@types/dompurify": "^3.2.0"
135137
}
136138
}

web/src/utils/markdownSanitization.ts

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { sanitizeUrl } from "./urlValidation";
2+
import DOMPurify from "dompurify";
23

34
const sanitizeRepeated = (text: string, pattern: RegExp, replacement: string): string => {
45
let result = text;
@@ -27,29 +28,25 @@ export const sanitizeMarkdown = (markdown: string): string => {
2728
return `[${text}](${sanitizedUrl})`;
2829
});
2930

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+
});
5246

47+
// Optional: Remove encoded protocols/entities as before
48+
sanitized = sanitized.replace(/javascript:/gi, "");
49+
sanitized = sanitized.replace(/vbscript:/gi, "");
5350
sanitized = sanitized.replace(/&#x[0-9a-f]+;/gi, "");
5451
sanitized = sanitized.replace(/&#[0-9]+;/gi, "");
5552

0 commit comments

Comments
 (0)