diff --git a/lib/icons/sanitize.js b/lib/icons/sanitize.js new file mode 100644 index 0000000..0d6e518 --- /dev/null +++ b/lib/icons/sanitize.js @@ -0,0 +1,16 @@ +// lib/icons/sanitize.js +// Focused SVG sanitizer for owner-uploaded icons. NOT a general-purpose +// sanitizer — it removes the script/handler/foreignObject/js-uri vectors that +// matter for inline-rendered icons. (Owner-only upload behind CF Access.) +export function sanitizeSvg(input) { + let s = Buffer.isBuffer(input) ? input.toString('utf8') : String(input); + s = s.replace(//gi, ''); + s = s.replace(//gi, ''); + s = s.replace(/\son[a-z]+\s*=\s*"[^"]*"/gi, ''); + s = s.replace(/\son[a-z]+\s*=\s*'[^']*'/gi, ''); + // Unquoted handlers, e.g. . Value runs until whitespace, + // quote, or the tag's closing > / />. + s = s.replace(/\son[a-z]+\s*=\s*[^\s">]+/gi, ''); + s = s.replace(/(href|xlink:href)\s*=\s*("|')\s*javascript:[^"']*\2/gi, '$1=$2#$2'); + return s; +} diff --git a/tests/icons/sanitize.test.js b/tests/icons/sanitize.test.js new file mode 100644 index 0000000..f268392 --- /dev/null +++ b/tests/icons/sanitize.test.js @@ -0,0 +1,29 @@ +import { describe, it, expect } from 'vitest'; +import { sanitizeSvg } from '../../lib/icons/sanitize.js'; + +describe('sanitizeSvg', () => { + it('strips