CVE-2017-14922: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Stored XSS vulnerability via IMG element at "History" of Profile, Calendar, Tasks, and CRM in Tine 2.0 Community Edition before 2017.08.4 allows an authenticated user to inject JavaScript, which is mishandled during rendering by the application administrator and other users.
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: 2017-09-30T01:29Z
Repository: https://github.com/tine20/Tine-2.0-Open-Source-Groupware-and-CRM
Language: JavaScript
Files changed: tine20/Filemanager/js/NodeEditDialog.js, tine20/Filemanager/js/nodeActions.js, tine20/Tinebase/js/widgets/container/TreePanel.js
Commit date: 2017-09-08 18:24:32 +0200
Commit message: node delte might fail

Change-Id: Ifa3694efacc0e0ac71792b0d67999c946b4f4712

Diff: diff --git a/tine20/Filemanager/js/NodeEditDialog.js b/tine20/Filemanager/js/NodeEditDialog.js
index 91e0d093ff..2b7770d601 100644
--- a/tine20/Filemanager/js/NodeEditDialog.js
+++ b/tine20/Filemanager/js/NodeEditDialog.js
@@ -191,10 +191,11 @@ Tine.Filemanager.NodeEditDialog = Ext.extend(Tine.widgets.dialog.EditDialog, {
                                 }, {
                                     xtype: 'displayfield',
                                     name: 'path',
                                     hideLabel: true,
                                     fieldClass: 'x-ux-displayfield-text',
+                                    htmlEncode: true,
                                     columnWidth: 1
                                 }],[
                                 Tine.widgets.form.RecordPickerManager.get('Addressbook', 'Contact', {
                                     userOnly: true,
                                     useAccountRecord: true,
diff --git a/tine20/Filemanager/js/nodeActions.js b/tine20/Filemanager/js/nodeActions.js
index 5be9050716..673773c169 100644
--- a/tine20/Filemanager/js/nodeActions.js
+++ b/tine20/Filemanager/js/nodeActions.js
@@ -200,17 +200,13 @@ Tine.Filemanager.nodeActions.Delete = {
             nodes = this.initialConfig.selections;
 
         if (nodes && nodes.length) {
             for (var i = 0; i < nodes.length; i++) {
                 var currNodeData = nodes[i].data;
-
-                if (typeof currNodeData.name == 'object') {
-                    nodeName += currNodeData.name.name + '<br />';
-                }
-                else {
-                    nodeName += currNodeData.name + '<br />';
-                }
+                nodeName += Tine.Tinebase.EncodingHelper.encode(typeof currNodeData.name == 'object' ?
+                    currNodeData.name.name :
+                    currNodeData.name) + '<br />';
             }
         }
 
         this.conflictConfirmWin = Tine.widgets.dialog.FileListDialog.openWindow({
             modal: true,
diff --git a/tine20/Tinebase/js/widgets/container/TreePanel.js b/tine20/Tinebase/js/widgets/container/TreePanel.js
index a0bae6d9dc..aeb622f833 100644
--- a/tine20/Tinebase/js/widgets/container/TreePanel.js
+++ b/tine20/Tinebase/js/widgets/container/TreePanel.js
@@ -593,16 +593,19 @@ Ext.extend(Tine.widgets.container.TreePanel, Ext.tree.TreePanel, {
         if (! attr.name && attr.path) {
             attr.name = Tine.Tinebase.container.path2name(attr.path, this.containerName, this.containersName);
         }
 
         Ext.applyIf(attr, {
-            text: Ext.util.Format.htmlEncode(attr.name),
-            qtip: Tine.Tinebase.common.doubleEncode(attr.name),
+            text: attr.name,
+            qtip: attr.name,
             leaf: !!attr.account_grants,
             allowDrop: !!attr.account_grants && attr.account_grants.addGrant
         });
 
+        attr.text = Tine.Tinebase.EncodingHelper.encode(attr.text);
+        attr.qtip = Tine.Tinebase.EncodingHelper.encode(attr.qtip);
+
         // copy 'real' data to container space
         attr.container = Ext.copyTo({}, attr, Tine.Tinebase.Model.Container.getFieldNames());
     },
 
     /**

Vulnerable code: 
                if (typeof currNodeData.name == 'object') {
                    nodeName += currNodeData.name.name + '<br />';
                }
                else {
                    nodeName += currNodeData.name + '<br />';
                }
            text: Ext.util.Format.htmlEncode(attr.name),
            qtip: Tine.Tinebase.common.doubleEncode(attr.name),
Fixed code:                                     htmlEncode: true,
                nodeName += Tine.Tinebase.EncodingHelper.encode(typeof currNodeData.name == 'object' ?
                    currNodeData.name.name :
                    currNodeData.name) + '<br />';
            text: attr.name,
            qtip: attr.name,
        attr.text = Tine.Tinebase.EncodingHelper.encode(attr.text);
        attr.qtip = Tine.Tinebase.EncodingHelper.encode(attr.qtip);