CVE-2022-4928: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A vulnerability was found in icplayer up to 0.819. It has been declared as problematic. Affected by this vulnerability is the function AddonText_Selection_create of the file addons/Text_Selection/src/presenter.js. The manipulation leads to cross site scripting. The attack can be launched remotely. Upgrading to version 0.820 is able to address this issue. The identifier of the patch is 2223628e6db1df73f6d633d2c0422d995990f0a3. It is recommended to upgrade the affected component. The identifier VDB-222289 was assigned to this vulnerability.
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: 6.1
Published: 2023-03-06T01:15Z
Repository: https://github.com/icplayer/icplayer
Language: JavaScript
Files changed: addons/Text_Selection/src/presenter.js, changelog.txt
Commit date: 2022-12-20 11:57:27 +0100
Commit message: Secure Text Selection addon against xss attacks, re #8593 (#881)

* sanitize Wiris response against XSS in the Wiris addon

* added tests

* Secure Text Selection addon against xss attacks

Co-authored-by: Maciej Zawłocki <mzawlocki@solwit.com>
Co-authored-by: maciej-zawlocki-solwit <34648176+maciej-zawlocki-solwit@users.noreply.github.com>
Co-authored-by: Michal-sw-solwit <100777673+Michal-sw-solwit@users.noreply.github.com>
Diff: diff --git a/addons/Text_Selection/src/presenter.js b/addons/Text_Selection/src/presenter.js
index 843e9613..e9ae1a06 100644
--- a/addons/Text_Selection/src/presenter.js
+++ b/addons/Text_Selection/src/presenter.js
@@ -1556,12 +1556,14 @@ function AddonText_Selection_create() {
         }
         speak(textVoices);
     };
 
     presenter.getWordsTextVoices = function($element) {
-        var $clone = $element.clone();
-        $clone.find('.selectable').each(function(){
+        var sanitizedHTML = window.xssUtils.sanitize($element[0].outerHTML);
+        var $sanitizedElement = $(sanitizedHTML);
+
+        $($sanitizedElement).find('.selectable').each(function(){
             var $this = $(this);
 
             if ($this.hasClass('selected')) {
                 $this.html(SPLIT + $this.html() + SPLIT + SELECTED + SPLIT);
             }
@@ -1572,11 +1574,11 @@ function AddonText_Selection_create() {
             } else if ($this.hasClass('correct')) {
                 $this.html(SPLIT + $this.html() + SPLIT + CORRECT + SPLIT);
             }
         });
 
-        var textArray = presenter.getTextFromElementWithAltTexts($clone).split(SPLIT);
+        var textArray = presenter.getTextFromElementWithAltTexts($sanitizedElement).split(SPLIT);
 
         var textVoices = [];
 
         for(var i = 0; i < textArray.length; i++) {
             if(textArray[i].trim().length == 0) continue;
@@ -1593,14 +1595,16 @@ function AddonText_Selection_create() {
 
         return textVoices;
     };
 
     presenter.getPhrasesTextVoices = function($element) {
-        var $clone = $element.clone();
+        var sanitizedHTML = window.xssUtils.sanitize($element[0].outerHTML);
+        var $sanitizedElement = $(sanitizedHTML);
 
-        $clone.find('.selectable').each(function(index){
+        $sanitizedElement.find('.selectable').each(function(index){
             var $this = $(this);
+
             $this.html(SPLIT + PHRASE + ' ' + (index+1) + SPLIT + $this.html() + SPLIT + PHRASE_END + SPLIT );
 
             if ($this.hasClass('selected')) {
                 $this.html($this.html() + SELECTED + SPLIT);
             }
@@ -1611,11 +1615,11 @@ function AddonText_Selection_create() {
             } else if ($this.hasClass('correct')) {
                 $this.html($this.html() + CORRECT + SPLIT);
             }
         });
 
-        var textArray = presenter.getTextFromElementWithAltTexts($clone).split(SPLIT);
+        var textArray = presenter.getTextFromElementWithAltTexts($sanitizedElement).split(SPLIT);
 
         var textVoices = [];
 
         for(var i = 0; i < textArray.length; i++) {
             if(textArray[i].trim().length == 0) continue;
@@ -1645,11 +1649,10 @@ function AddonText_Selection_create() {
         $el.before($('<span>' + start_text + '</span>'));
         $el.after($('<span>' + end_text + '</span>'));
     }
 
     presenter.getSectionsTextVoices = function($element) {
-
         var $clone = $element.clone();
 
         $clone.find('.selectable').each(function(){
             var $this = $(this);
 
diff --git a/changelog.txt b/changelog.txt
index a4bdc5aa..f0d74190 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -7,10 +7,11 @@
 2022-12-06 Fixed functionality to auto set in correct order groups' modules in view
 2022-11-28 Added ModuleScript property
 2022-11-25 Removed pause while reading syntax about time for TTS
 2022-11-25 Fixed TTS reading an extra comma when alt text with dot is present at the end of a list element  
 2022-11-25 Fixed no break in tts at the end of a line of text.
+2022-11-22 Secured Text Selection addon against xss attacks
 2022-11-14 Fixed support for only one audio type in slideshow addon
 2022-11-10 Added grid size and rulers position separation
 2022-11-07 Added worksWithAll property to eKeyboard
 2022-11-03 Fixed bug with reading whole HTML elements instead of their content in TTS for Text Coloring
 2022-11-03 Added LottiePlayer module

Vulnerable code:         var $clone = $element.clone();
        $clone.find('.selectable').each(function(){
        var textArray = presenter.getTextFromElementWithAltTexts($clone).split(SPLIT);
        var $clone = $element.clone();
        $clone.find('.selectable').each(function(index){
        var textArray = presenter.getTextFromElementWithAltTexts($clone).split(SPLIT);

Fixed code:         var sanitizedHTML = window.xssUtils.sanitize($element[0].outerHTML);
        var $sanitizedElement = $(sanitizedHTML);

        $($sanitizedElement).find('.selectable').each(function(){
        var textArray = presenter.getTextFromElementWithAltTexts($sanitizedElement).split(SPLIT);
        var sanitizedHTML = window.xssUtils.sanitize($element[0].outerHTML);
        var $sanitizedElement = $(sanitizedHTML);
        $sanitizedElement.find('.selectable').each(function(index){

        var textArray = presenter.getTextFromElementWithAltTexts($sanitizedElement).split(SPLIT);
2022-11-22 Secured Text Selection addon against xss attacks