CVE-2022-4735: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A vulnerability classified as problematic was found in asrashley dash-live. This vulnerability affects the function ready of the file static/js/media.js of the component DOM Node Handler. The manipulation leads to cross site scripting. The attack can be initiated remotely. The name of the patch is 24d01757a5319cc14c4aa1d8b53d1ab24d48e451. It is recommended to apply a patch to fix this issue. VDB-216766 is the identifier 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: 2022-12-25T16:15Z
Repository: https://github.com/asrashley/dash-live
Language: JavaScript
Files changed: static/js/media.js
Commit date: 2022-03-01 13:54:02 +0000
Commit message: escape strings before using them in HTML tags

Extracting text from a DOM node and interpreting it as HTML can lead
to a cross-site scripting vulnerability.

Diff: diff --git a/static/js/media.js b/static/js/media.js
index 35a881f..053f978 100644
--- a/static/js/media.js
+++ b/static/js/media.js
@@ -155,29 +155,35 @@ $(document).ready(function(){
             return;
         }
         csrf = $('#media-files').data('csrf');
         console.log('index blob',blobId, csrf);
         dialog = $('#dialog-box')
-        dialog.find(".modal-body").html('<p>Indexing ' + filename + '</p><div class="error"></div>');
+        dialog.find(".modal-body").html('<p>Indexing ' + encodeURIComponent(filename) +
+                                        '</p><div class="error"></div>');
         showDialog();
         $.ajax({
             url: '/media/'+blobId+'?index=1&csrf_token='+csrf,
             method: 'GET',
             dataType: 'json',
         }).done(function(result) {
             if(result.error) {
               var i;
               dialog.find('.modal-body .error').text(result.error);
             } else {
-                dialog.find(".modal-body").html('<p>Indexing ' + filename + ' complete</p>');
+                dialog.find(".modal-body").html('<p>Indexing ' +
+                                                encodeURIComponent(filename) +
+                                                ' complete</p>');
                 if (result.representation) {
                     $row.find('td.codec').text(result.representation.codecs);
                     if(result.representation.encrypted) {
                         $row.find('td.encrypted').html('<span class="bool-yes ">&check;</span>');
                         $row.find('td.kid').html("");
                         for(i=0; i < result.representation.kids.length; ++i) {
-                          $row.find('td.kid').append('<p>'+result.representation.kids[i]+'</p>');
+                            $row.find('td.kid').append(
+                                '<p>' +
+                                encodeURIComponent(result.representation.kids[i]) +
+                                '</p>');
                         }
                     } else {
                         $row.find('td.encrypted').html('<span class="bool-no ">&cross;</span>');
                     }
                     $row.find('.btn-index').addClass('btn-info').removeClass('btn-warning').text('Re-index');
@@ -239,11 +245,13 @@ $(document).ready(function(){
         }
         form.find('input[name="ajax"]').val("1");
         data = new FormData(form[0]);
         $("#upload-form .submit").prop("disabled", true);
         dialog = $('#dialog-box')
-        dialog.find(".modal-body").html('<p>Uploading ' + filename + '</p><div class="error"></div>');
+        dialog.find(".modal-body").html('<p>Uploading ' +
+                                        encodeURIComponent(filename) +
+                                        '</p><div class="error"></div>');
         showDialog();
         $.ajax({
             url: form.attr("action"),
             data: data,
             type: "POST",
@@ -259,11 +267,13 @@ $(document).ready(function(){
             if(data.error) {
                 err = dialog.find('.modal-body .error');
                 err.text(data.error);
                 return;
             }
-            dialog.find(".modal-body").html('<p>Finished uploading ' + filename+ '<span class="bool-yes ">&check;</span>');
+            dialog.find(".modal-body").html('<p>Finished uploading ' +
+                                            encodeURIComponent(filename) +
+                                            '<span class="bool-yes ">&check;</span>');
             if(data.upload_url) {
                 $('#upload-form').attr('action', data.upload_url);
             }
             if(data.csrf_token) {
                 $('#upload-form input[name="csrf_token"]').val(data.csrf);

Vulnerable code:         dialog.find(".modal-body").html('<p>Indexing ' + filename + '</p><div class="error"></div>');
                dialog.find(".modal-body").html('<p>Indexing ' + filename + ' complete</p>');
                          $row.find('td.kid').append('<p>'+result.representation.kids[i]+'</p>');
        dialog.find(".modal-body").html('<p>Uploading ' + filename + '</p><div class="error"></div>');
            dialog.find(".modal-body").html('<p>Finished uploading ' + filename+ '<span class="bool-yes ">&check;</span>');
Fixed code:         dialog.find(".modal-body").html('<p>Indexing ' + encodeURIComponent(filename) +
                                        '</p><div class="error"></div>');
                dialog.find(".modal-body").html('<p>Indexing ' +
                                                encodeURIComponent(filename) +
                                                ' complete</p>');
                            $row.find('td.kid').append(
                                '<p>' +
                                encodeURIComponent(result.representation.kids[i]) +
                                '</p>');
        dialog.find(".modal-body").html('<p>Uploading ' +
                                        encodeURIComponent(filename) +
                                        '</p><div class="error"></div>');
            dialog.find(".modal-body").html('<p>Finished uploading ' +
                                            encodeURIComponent(filename) +
                                            '<span class="bool-yes ">&check;</span>');