Vulnerability: Cross-site Scripting in Scratch-Svg-Renderer A DOM-based cross-site scripting (XSS) vulnerability in Scratch-Svg-Renderer v0.2.0 allows attackers to execute arbitrary web scripts or HTML via a crafted sb3 file.
Vulnerability ID: GHSA-h3vq-wv8j-36gw
CWE: CWE-79
Severity score: 0
Project: https://github.com/LLK/scratch-svg-renderer
Published: 2022-01-08
File: src/fixup-svg-string.js
Commit message: Remove lots of event handlers
Commit author: Eric Rosenbaum

Vulnerable version (before fix):
 module.exports = function (svgString) {     // Empty script tags and javascript executing     svgString = svgString.replace(/<script[\s\S]*>[\s\S]*<\/script>/, '<script></script>');          // Remove error handlers     svgString = svgString.replace(/onerror=[\s\S]*['"].*?['"]/i, '');      return svgString; };

Fixed version (after fix):
 module.exports = function (svgString) {     // Empty script tags and javascript executing     svgString = svgString.replace(/<script[\s\S]*>[\s\S]*<\/script>/, '<script></script>');          // Remove event handlers     const eventNames = [         'onbegin', 'onend', 'onrepeat', 'onabort', 'onerror', 'onresize', 'onscroll', 'onunload', 'oncopy',         'oncut', 'onpaste', 'oncancel', 'oncanplay', 'oncanplaythrough', 'onchange', 'onclick', 'onclose',         'oncuechange', 'ondblclick', 'ondrag', 'ondragend', 'ondragenter', 'ondragexit', 'ondragleave',         'ondragover', 'ondragstart', 'ondrop', 'ondurationchange', 'onloadeddata', 'onloadedmetadata',         'onloadstart', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove',         'onemptied', 'onended', 'onerror', 'onfocus', 'oninput', 'oninvalid', 'onkeydown', 'onkeypress',         'onkeyup', 'onload', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onpause', 'onplay',         'onplaying', 'onprogress', 'onratechange', 'onreset', 'onresize', 'onscroll', 'onseeked', 'onseeking',         'onselect', 'onshow', 'onstalled', 'onsubmit', 'onsuspend', 'ontimeupdate', 'ontoggle', 'onvolumechange',         'onwaiting', 'onactivate', 'onfocusin', 'onfocusout'     ];     const eventsRegex = new RegExp(`(${eventNames.join('|')})\\s*=\\s*['"].*['"]`, 'i');     svgString = svgString.replace(eventsRegex, '');      return svgString; };

Patch:
patch: @@ -50,8 +50,21 @@ module.exports = function (svgString) {
     // Empty script tags and javascript executing
     svgString = svgString.replace(/<script[\s\S]*>[\s\S]*<\/script>/, '<script></script>');
     
-    // Remove error handlers
-    svgString = svgString.replace(/onerror=[\s\S]*['"].*?['"]/i, '');
+    // Remove event handlers
+    const eventNames = [
+        'onbegin', 'onend', 'onrepeat', 'onabort', 'onerror', 'onresize', 'onscroll', 'onunload', 'oncopy',
+        'oncut', 'onpaste', 'oncancel', 'oncanplay', 'oncanplaythrough', 'onchange', 'onclick', 'onclose',
+        'oncuechange', 'ondblclick', 'ondrag', 'ondragend', 'ondragenter', 'ondragexit', 'ondragleave',
+        'ondragover', 'ondragstart', 'ondrop', 'ondurationchange', 'onloadeddata', 'onloadedmetadata',
+        'onloadstart', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove',
+        'onemptied', 'onended', 'onerror', 'onfocus', 'oninput', 'oninvalid', 'onkeydown', 'onkeypress',
+        'onkeyup', 'onload', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onpause', 'onplay',
+        'onplaying', 'onprogress', 'onratechange', 'onreset', 'onresize', 'onscroll', 'onseeked', 'onseeking',
+        'onselect', 'onshow', 'onstalled', 'onsubmit', 'onsuspend', 'ontimeupdate', 'ontoggle', 'onvolumechange',
+        'onwaiting', 'onactivate', 'onfocusin', 'onfocusout'
+    ];
+    const eventsRegex = new RegExp(`(${eventNames.join('|')})\\s*=\\s*['"].*['"]`, 'i');
+    svgString = svgString.replace(eventsRegex, '');
 
     return svgString;
 };
path: src/fixup-svg-string.js