This repository has been archived on 2026-08-17. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
beenvoice-web/src/lib/svg-sanitize.ts
T

39 lines
1.4 KiB
TypeScript

import "server-only";
/**
* Lightweight defense-in-depth pass over uploaded SVG markup before it is
* stored. Strips executable content (scripts, event handlers, external
* references) so a malicious SVG can't run script if it's ever rendered
* inline (dangerouslySetInnerHTML) rather than via <img src>. Not a full
* parser — good enough for a self-uploaded logo, not a substitute for
* treating SVG as active content from an untrusted source.
*/
export function sanitizeSvg(input: string): string {
let svg = input;
// Strip <script>...</script> blocks and self-closing <script/> tags.
svg = svg.replace(/<script[\s\S]*?<\/script\s*>/gi, "");
svg = svg.replace(/<script\b[^>]*\/>/gi, "");
// Strip on* event handler attributes (onload, onclick, onerror, ...).
svg = svg.replace(/\son\w+\s*=\s*"[^"]*"/gi, "");
svg = svg.replace(/\son\w+\s*=\s*'[^']*'/gi, "");
svg = svg.replace(/\son\w+\s*=\s*[^\s>]+/gi, "");
// Strip javascript: URIs in href/xlink:href/src attributes.
svg = svg.replace(
/((?:xlink:href|href|src)\s*=\s*)"javascript:[^"]*"/gi,
'$1""',
);
svg = svg.replace(
/((?:xlink:href|href|src)\s*=\s*)'javascript:[^']*'/gi,
"$1''",
);
// Strip <foreignObject> (can embed arbitrary HTML) and <iframe>.
svg = svg.replace(/<foreignObject[\s\S]*?<\/foreignObject\s*>/gi, "");
svg = svg.replace(/<iframe[\s\S]*?<\/iframe\s*>/gi, "");
return svg;
}