CVE-2021-43862: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: jQuery Terminal Emulator is a plugin for creating command line interpreters in your applications. Versions prior to 2.31.1 contain a low impact and limited cross-site scripting (XSS) vulnerability. The code for XSS payload is always visible, but an attacker can use other techniques to hide the code the victim sees. If the application uses the `execHash` option and executes code from URL, the attacker can use this URL to execute their code. The scope is limited because the javascript attribute used is added to span tag, so no automatic execution like with `onerror` on images is possible. This issue is fixed in version 2.31.1. As a workaround, the user can use formatting that wrap whole user input and its no op. The code for this workaround is available in the GitHub Security Advisory. The fix will only work when user of the library is not using different formatters (e.g. to highlight code in different way).
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: 2021-12-30T15:15Z
Repository: https://github.com/jcubic/jquery.terminal
Language: JavaScript
Files changed: CHANGELOG.md, js/jquery.terminal-src.js
Commit date: 2021-12-30 11:56:18 +0100
Commit message: fix Self XSS by injecting data attrbutte #727

Diff: diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2e6ddd88..0d19424f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
+## 2.31.1
+### Bugfix
+* fixing low severity self XSS with potential more security implications [#727](https://github.com/jcubic/jquery.terminal/issues/727)
+
 ## 2.31.0
 ### Breaking
 * remove undocumented `echo_command` (that was used by old `echo_newline` extension)
 ### Features
 * scroll to bottom for each line in multiline typing animation
diff --git a/js/jquery.terminal-2.31.0.js b/js/jquery.terminal-2.31.0.js
index bc886823..d1a4269f 100644
Binary files a/js/jquery.terminal-2.31.0.js and b/js/jquery.terminal-2.31.0.js differ
diff --git a/js/jquery.terminal-2.31.0.min.js b/js/jquery.terminal-2.31.0.min.js
index 80360ec9..24a84017 100644
Binary files a/js/jquery.terminal-2.31.0.min.js and b/js/jquery.terminal-2.31.0.min.js differ
diff --git a/js/jquery.terminal-src.js b/js/jquery.terminal-src.js
index f078322f..f6e701f5 100644
--- a/js/jquery.terminal-src.js
+++ b/js/jquery.terminal-src.js
@@ -6178,11 +6178,13 @@
             function clean_data(data, text) {
                 if (data === '') {
                     return text;
                 } else {
                     return data.replace(/&#93;/g, ']')
-                        .replace(/>/g, '&gt;').replace(/</g, '&lt;');
+                        .replace(/>/g, '&gt;')
+                        .replace(/</g, '&lt;')
+                        .replace(/"/g, '&quot;');
                 }
             }
             // -----------------------------------------------------------------
             function add_attrs(attrs) {
                 if (attrs) {
@@ -6363,11 +6365,11 @@
                 if (style.indexOf('!') !== -1) {
                     result += ' data-text>' + text + '</a>';
                 } else if (style.indexOf('@') !== -1) {
                     result += ' data-text/>';
                 } else {
-                    result += ' data-text="' + data.replace(/"/g, '&quot;') + '">' +
+                    result += ' data-text="' + data + '">' +
                         '<span>' + text + '</span></span>';
                 }
                 return result;
             }
             if (typeof str === 'string') {
@@ -6384,11 +6386,11 @@
                         });
                         return text.replace(format_parts_re, format);
                     } else {
                         text = safe(text);
                         text = text.replace(/\\\]/, '&#93;');
-                        var data = text;
+                        var data = clean_data(text);
                         var extra = extra_css(text, settings);
                         var prefix;
                         if (extra.length) {
                             text = wide_characters(text, settings);
                             prefix = '<span style="' + extra + '"';
diff --git a/js/jquery.terminal.js b/js/jquery.terminal.js
index bc886823..d1a4269f 100644
Binary files a/js/jquery.terminal.js and b/js/jquery.terminal.js differ
diff --git a/js/jquery.terminal.min.js b/js/jquery.terminal.min.js
index 80360ec9..24a84017 100644
Binary files a/js/jquery.terminal.min.js and b/js/jquery.terminal.min.js differ
diff --git a/js/jquery.terminal.min.js.map b/js/jquery.terminal.min.js.map
index 5dd95c86..911765da 100644
Binary files a/js/jquery.terminal.min.js.map and b/js/jquery.terminal.min.js.map differ

Vulnerable code:                         .replace(/>/g, '&gt;').replace(/</g, '&lt;');
                    result += ' data-text="' + data.replace(/"/g, '&quot;') + '">' +
                        var data = text;
Fixed code: ## 2.31.1
### Bugfix
* fixing low severity self XSS with potential more security implications [#727](https://github.com/jcubic/jquery.terminal/issues/727)

                        .replace(/>/g, '&gt;')
                        .replace(/</g, '&lt;')
                        .replace(/"/g, '&quot;');
                    result += ' data-text="' + data + '">' +
                        var data = clean_data(text);