CVE-2020-7642: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: lazysizes through 5.2.0 allows execution of malicious JavaScript. The following attributes are not sanitized by the video-embed plugin: data-vimeo, data-vimeoparams, data-youtube and data-ytparams which can be abused to inject malicious JavaScript.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 5.4
Published: 2020-04-22T16:15Z
Repository: https://github.com/aFarkas/lazysizes
Language: JavaScript
Files changed: plugins/video-embed/ls.video-embed.js, plugins/video-embed/ls.video-embed.min.js
Commit date: 2020-04-15 09:59:40 +0200
Commit message: Video embed: test yt/vimeo id (fixes #764)

Diff: diff --git a/plugins/video-embed/ls.video-embed.js b/plugins/video-embed/ls.video-embed.js
index fdab5d0..8a0d6e7 100644
--- a/plugins/video-embed/ls.video-embed.js
+++ b/plugins/video-embed/ls.video-embed.js
@@ -25,10 +25,11 @@
 	;
 	var idIndex = Date.now();
 	var regId = /\{\{id}}/;
 	var regYtImg = /\{\{hqdefault}}/;
 	var regAmp = /^&/;
+	var regValidParam = /^[a-z0-9-_&=]+$/i;
 	var youtubeImg = protocol + '//img.youtube.com/vi/{{id}}/{{hqdefault}}.jpg';
 	var youtubeIframe = protocol + '//www.youtube.com/embed/{{id}}?autoplay=1';
 	var vimeoApi = protocol + '//vimeo.com/api/oembed.json?url=https%3A//vimeo.com/{{id}}';
 	var vimeoIframe = protocol + '//player.vimeo.com/video/{{id}}?autoplay=1';
 
@@ -62,21 +63,26 @@
 	function embedVimeoIframe(e){
 		var elem = e.currentTarget;
 		var id = elem.getAttribute('data-vimeo');
 		var vimeoParams = elem.getAttribute('data-vimeoparams') || '';
 
+		elem.removeEventListener('click', embedVimeoIframe);
+
+		if (!id || !regValidParam.test(id) || (vimeoParams && !regValidParam.test(vimeoParams))) {
+			return;
+		}
+
 		if(vimeoParams && !regAmp.test(vimeoParams)){
 			vimeoParams = '&'+ vimeoParams;
 		}
 
 		e.preventDefault();
 
 		elem.innerHTML = '<iframe src="' + (vimeoIframe.replace(regId, id)) + vimeoParams +'" ' +
 			'frameborder="0" allowfullscreen="" width="640" height="390"></iframe>'
 		;
 
-		elem.removeEventListener('click', embedVimeoIframe);
 	}
 
 	function embedYoutubeImg(id, elem){
 		var ytImg = elem.getAttribute('data-thumb-size') || lazySizes.cfg.ytThumb || 'hqdefault';
 
@@ -87,21 +93,25 @@
 	function embedYoutubeIframe(e){
 		var elem = e.currentTarget;
 		var id = elem.getAttribute('data-youtube');
 		var youtubeParams = elem.getAttribute('data-ytparams') || '';
 
+		elem.removeEventListener('click', embedYoutubeIframe);
+
+		if (!id || !regValidParam.test(id) || (youtubeParams && !regValidParam.test(youtubeParams))) {
+			return;
+		}
+
 		if(youtubeParams && !regAmp.test(youtubeParams)){
 			youtubeParams = '&'+ youtubeParams;
 		}
 
 		e.preventDefault();
 
 		elem.innerHTML = '<iframe src="' + (youtubeIframe.replace(regId, id)) + youtubeParams +'" ' +
 			'frameborder="0" allowfullscreen="" width="640" height="390"></iframe>'
 		;
-
-		elem.removeEventListener('click', embedYoutubeIframe);
 	}
 
 	document.addEventListener('lazybeforeunveil', function(e){
 		if(e.detail.instance != lazySizes){return;}
 
diff --git a/plugins/video-embed/ls.video-embed.min.js b/plugins/video-embed/ls.video-embed.min.js
index 2cb57a4..123d28b 100644
--- a/plugins/video-embed/ls.video-embed.min.js
+++ b/plugins/video-embed/ls.video-embed.min.js
@@ -1,2 +1,2 @@
 /*! lazysizes - v5.2.0 */
-!function(a,b){if(a){var c=function(){b(a.lazySizes),a.removeEventListener("lazyunveilread",c,!0)};b=b.bind(null,a,a.document),"object"==typeof module&&module.exports?b(require("lazysizes")):a.lazySizes?c():a.addEventListener("lazyunveilread",c,!0)}}("undefined"!=typeof window?window:0,function(a,b,c){"use strict";function d(c,d){var e="vimeoCallback"+j,f=b.createElement("script");c+="&callback="+e,j++,a[e]=function(b){f.parentNode.removeChild(f),delete a[e],d(b)},f.src=c,b.head.appendChild(f)}function e(a,b){d(p.replace(k,a),function(a){a&&a.thumbnail_url&&(b.style.backgroundImage="url("+a.thumbnail_url+")")}),b.addEventListener("click",f)}function f(a){var b=a.currentTarget,c=b.getAttribute("data-vimeo"),d=b.getAttribute("data-vimeoparams")||"";d&&!m.test(d)&&(d="&"+d),a.preventDefault(),b.innerHTML='<iframe src="'+q.replace(k,c)+d+'" frameborder="0" allowfullscreen="" width="640" height="390"></iframe>',b.removeEventListener("click",f)}function g(a,b){var d=b.getAttribute("data-thumb-size")||c.cfg.ytThumb||"hqdefault";b.style.backgroundImage="url("+n.replace(k,a).replace(l,d)+")",b.addEventListener("click",h)}function h(a){var b=a.currentTarget,c=b.getAttribute("data-youtube"),d=b.getAttribute("data-ytparams")||"";d&&!m.test(d)&&(d="&"+d),a.preventDefault(),b.innerHTML='<iframe src="'+o.replace(k,c)+d+'" frameborder="0" allowfullscreen="" width="640" height="390"></iframe>',b.removeEventListener("click",h)}if(b.getElementsByClassName){var i="https:"==location.protocol?"https:":"http:",j=Date.now(),k=/\{\{id}}/,l=/\{\{hqdefault}}/,m=/^&/,n=i+"//img.youtube.com/vi/{{id}}/{{hqdefault}}.jpg",o=i+"//www.youtube.com/embed/{{id}}?autoplay=1",p=i+"//vimeo.com/api/oembed.json?url=https%3A//vimeo.com/{{id}}",q=i+"//player.vimeo.com/video/{{id}}?autoplay=1";b.addEventListener("lazybeforeunveil",function(a){if(a.detail.instance==c){var b=a.target,d=b.getAttribute("data-youtube"),f=b.getAttribute("data-vimeo");d&&b&&g(d,b),f&&b&&e(f,b)}})}});
\ No newline at end of file
+!function(a,b){if(a){var c=function(){b(a.lazySizes),a.removeEventListener("lazyunveilread",c,!0)};b=b.bind(null,a,a.document),"object"==typeof module&&module.exports?b(require("lazysizes")):a.lazySizes?c():a.addEventListener("lazyunveilread",c,!0)}}("undefined"!=typeof window?window:0,function(a,b,c){"use strict";function d(c,d){var e="vimeoCallback"+j,f=b.createElement("script");c+="&callback="+e,j++,a[e]=function(b){f.parentNode.removeChild(f),delete a[e],d(b)},f.src=c,b.head.appendChild(f)}function e(a,b){d(q.replace(k,a),function(a){a&&a.thumbnail_url&&(b.style.backgroundImage="url("+a.thumbnail_url+")")}),b.addEventListener("click",f)}function f(a){var b=a.currentTarget,c=b.getAttribute("data-vimeo"),d=b.getAttribute("data-vimeoparams")||"";b.removeEventListener("click",f),c&&n.test(c)&&(!d||n.test(d))&&(d&&!m.test(d)&&(d="&"+d),a.preventDefault(),b.innerHTML='<iframe src="'+r.replace(k,c)+d+'" frameborder="0" allowfullscreen="" width="640" height="390"></iframe>')}function g(a,b){var d=b.getAttribute("data-thumb-size")||c.cfg.ytThumb||"hqdefault";b.style.backgroundImage="url("+o.replace(k,a).replace(l,d)+")",b.addEventListener("click",h)}function h(a){var b=a.currentTarget,c=b.getAttribute("data-youtube"),d=b.getAttribute("data-ytparams")||"";b.removeEventListener("click",h),c&&n.test(c)&&(!d||n.test(d))&&(d&&!m.test(d)&&(d="&"+d),a.preventDefault(),b.innerHTML='<iframe src="'+p.replace(k,c)+d+'" frameborder="0" allowfullscreen="" width="640" height="390"></iframe>')}if(b.getElementsByClassName){var i="https:"==location.protocol?"https:":"http:",j=Date.now(),k=/\{\{id}}/,l=/\{\{hqdefault}}/,m=/^&/,n=/^[a-z0-9-_&=]+$/i,o=i+"//img.youtube.com/vi/{{id}}/{{hqdefault}}.jpg",p=i+"//www.youtube.com/embed/{{id}}?autoplay=1",q=i+"//vimeo.com/api/oembed.json?url=https%3A//vimeo.com/{{id}}",r=i+"//player.vimeo.com/video/{{id}}?autoplay=1";b.addEventListener("lazybeforeunveil",function(a){if(a.detail.instance==c){var b=a.target,d=b.getAttribute("data-youtube"),f=b.getAttribute("data-vimeo");d&&b&&g(d,b),f&&b&&e(f,b)}})}});
\ No newline at end of file

Vulnerable code: 		elem.removeEventListener('click', embedVimeoIframe);

		elem.removeEventListener('click', embedYoutubeIframe);
!function(a,b){if(a){var c=function(){b(a.lazySizes),a.removeEventListener("lazyunveilread",c,!0)};b=b.bind(null,a,a.document),"object"==typeof module&&module.exports?b(require("lazysizes")):a.lazySizes?c():a.addEventListener("lazyunveilread",c,!0)}}("undefined"!=typeof window?window:0,function(a,b,c){"use strict";function d(c,d){var e="vimeoCallback"+j,f=b.createElement("script");c+="&callback="+e,j++,a[e]=function(b){f.parentNode.removeChild(f),delete a[e],d(b)},f.src=c,b.head.appendChild(f)}function e(a,b){d(p.replace(k,a),function(a){a&&a.thumbnail_url&&(b.style.backgroundImage="url("+a.thumbnail_url+")")}),b.addEventListener("click",f)}function f(a){var b=a.currentTarget,c=b.getAttribute("data-vimeo"),d=b.getAttribute("data-vimeoparams")||"";d&&!m.test(d)&&(d="&"+d),a.preventDefault(),b.innerHTML='<iframe src="'+q.replace(k,c)+d+'" frameborder="0" allowfullscreen="" width="640" height="390"></iframe>',b.removeEventListener("click",f)}function g(a,b){var d=b.getAttribute("data-thumb-size")||c.cfg.ytThumb||"hqdefault";b.style.backgroundImage="url("+n.replace(k,a).replace(l,d)+")",b.addEventListener("click",h)}function h(a){var b=a.currentTarget,c=b.getAttribute("data-youtube"),d=b.getAttribute("data-ytparams")||"";d&&!m.test(d)&&(d="&"+d),a.preventDefault(),b.innerHTML='<iframe src="'+o.replace(k,c)+d+'" frameborder="0" allowfullscreen="" width="640" height="390"></iframe>',b.removeEventListener("click",h)}if(b.getElementsByClassName){var i="https:"==location.protocol?"https:":"http:",j=Date.now(),k=/\{\{id}}/,l=/\{\{hqdefault}}/,m=/^&/,n=i+"//img.youtube.com/vi/{{id}}/{{hqdefault}}.jpg",o=i+"//www.youtube.com/embed/{{id}}?autoplay=1",p=i+"//vimeo.com/api/oembed.json?url=https%3A//vimeo.com/{{id}}",q=i+"//player.vimeo.com/video/{{id}}?autoplay=1";b.addEventListener("lazybeforeunveil",function(a){if(a.detail.instance==c){var b=a.target,d=b.getAttribute("data-youtube"),f=b.getAttribute("data-vimeo");d&&b&&g(d,b),f&&b&&e(f,b)}})}});
Fixed code: 	var regValidParam = /^[a-z0-9-_&=]+$/i;
		elem.removeEventListener('click', embedVimeoIframe);

		if (!id || !regValidParam.test(id) || (vimeoParams && !regValidParam.test(vimeoParams))) {
			return;
		}

		elem.removeEventListener('click', embedYoutubeIframe);

		if (!id || !regValidParam.test(id) || (youtubeParams && !regValidParam.test(youtubeParams))) {
			return;
		}

!function(a,b){if(a){var c=function(){b(a.lazySizes),a.removeEventListener("lazyunveilread",c,!0)};b=b.bind(null,a,a.document),"object"==typeof module&&module.exports?b(require("lazysizes")):a.lazySizes?c():a.addEventListener("lazyunveilread",c,!0)}}("undefined"!=typeof window?window:0,function(a,b,c){"use strict";function d(c,d){var e="vimeoCallback"+j,f=b.createElement("script");c+="&callback="+e,j++,a[e]=function(b){f.parentNode.removeChild(f),delete a[e],d(b)},f.src=c,b.head.appendChild(f)}function e(a,b){d(q.replace(k,a),function(a){a&&a.thumbnail_url&&(b.style.backgroundImage="url("+a.thumbnail_url+")")}),b.addEventListener("click",f)}function f(a){var b=a.currentTarget,c=b.getAttribute("data-vimeo"),d=b.getAttribute("data-vimeoparams")||"";b.removeEventListener("click",f),c&&n.test(c)&&(!d||n.test(d))&&(d&&!m.test(d)&&(d="&"+d),a.preventDefault(),b.innerHTML='<iframe src="'+r.replace(k,c)+d+'" frameborder="0" allowfullscreen="" width="640" height="390"></iframe>')}function g(a,b){var d=b.getAttribute("data-thumb-size")||c.cfg.ytThumb||"hqdefault";b.style.backgroundImage="url("+o.replace(k,a).replace(l,d)+")",b.addEventListener("click",h)}function h(a){var b=a.currentTarget,c=b.getAttribute("data-youtube"),d=b.getAttribute("data-ytparams")||"";b.removeEventListener("click",h),c&&n.test(c)&&(!d||n.test(d))&&(d&&!m.test(d)&&(d="&"+d),a.preventDefault(),b.innerHTML='<iframe src="'+p.replace(k,c)+d+'" frameborder="0" allowfullscreen="" width="640" height="390"></iframe>')}if(b.getElementsByClassName){var i="https:"==location.protocol?"https:":"http:",j=Date.now(),k=/\{\{id}}/,l=/\{\{hqdefault}}/,m=/^&/,n=/^[a-z0-9-_&=]+$/i,o=i+"//img.youtube.com/vi/{{id}}/{{hqdefault}}.jpg",p=i+"//www.youtube.com/embed/{{id}}?autoplay=1",q=i+"//vimeo.com/api/oembed.json?url=https%3A//vimeo.com/{{id}}",r=i+"//player.vimeo.com/video/{{id}}?autoplay=1";b.addEventListener("lazybeforeunveil",function(a){if(a.detail.instance==c){var b=a.target,d=b.getAttribute("data-youtube"),f=b.getAttribute("data-vimeo");d&&b&&g(d,b),f&&b&&e(f,b)}})}});