CVE-2022-1931 (published 2022-05-31T02:15Z)

Incorrect Synchronization in GitHub repository polonel/trudesk prior to 1.2.3.

Severity: MEDIUM
CVSS v2 base score: 5.5 (AV:N/AC:L/Au:S/C:P/I:P/A:N)
CVSS v3 base score: 8.1, HIGH (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N)

Weakness information:
cwe_id: CWE-662
cwe_name: Improper Synchronization
description: The product utilizes multiple threads or processes to allow temporary access to a shared resource that can only be exclusive to one process at a time, but it does not properly synchronize these actions, which might cause simultaneous accesses of this resource by multiple threads or processes.
extended_description: 
	   Synchronization refers to a variety of behaviors and mechanisms that allow two or more independently-operating processes or threads to ensure that they operate on shared resources in predictable ways that do not interfere with each other.  Some shared resource operations cannot be executed atomically; that is, multiple steps must be guaranteed to execute sequentially, without any interference by other processes.  Synchronization mechanisms vary widely, but they may include locking, mutexes, and semaphores.  When a multi-step operation on a shared resource cannot be guaranteed to execute independent of interference, then the resulting behavior can be unpredictable. Improper synchronization could lead to data or memory corruption, denial of service, etc.
	 
         

Fix information:
repo_url: https://github.com/polonel/trudesk
commit_details: repo_url: https://github.com/polonel/trudesk
author: Chris Brame
author_date: 2022-05-28 19:59:21-04:00
msg: fix(messages): validation check
repository: repo_url: https://github.com/polonel/trudesk
repo_name: polonel/trudesk
description:  :coffee: :seedling: Trudesk is an open-source help desk/ticketing solution.
repo_language: JavaScript
owner: polonel
file_changes: filename: TicketsContainer.jsx
change_type: ModificationType.MODIFY
diff: @@ -104,7 +104,6 @@ class TicketsContainer extends React.Component {
   }
 
   onTicketUpdated (data) {
-    console.log(data)
     this.props.ticketUpdated(data)
   }
 

programming_language: JavaScript
filename: messages.js
change_type: ModificationType.MODIFY
diff: @@ -14,9 +14,10 @@
 
 var async = require('async')
 var _ = require('lodash')
-var winston = require('winston')
+var winston = require('../../../logger')
 var ConversationSchema = require('../../../models/chat/conversation')
 var MessageSchema = require('../../../models/chat/message')
+var UserSchema = require('../../../models/user')
 
 var apiMessages = {}
 
@@ -191,22 +192,32 @@ apiMessages.send = function (req, res) {
   async.waterfall(
     [
       function (done) {
+        ConversationSchema.findOne({ _id: cId }, function (err, convo) {
+          if (err || !convo) return done('Invalid Conversation')
+
+          return done(null, convo)
+        })
+      },
+      function (convo, done) {
         // Updated conversation to save UpdatedAt field.
-        ConversationSchema.findOneAndUpdate({ _id: cId }, { updatedAt: new Date() }, { new: false }, function (
-          err,
-          convo
-        ) {
+        convo.updatedAt = new Date()
+        convo.save(function (err, savedConvo) {
           if (err) return done(err)
-          if (convo === null || convo === undefined) {
-            return done('Invalid Conversation: ' + convo)
-          }
-          return done(null, convo)
+
+          return done(null, savedConvo)
         })
       },
       function (convo, done) {
-        var Message = new MessageSchema({
+        UserSchema.findOne({ _id: owner }, function (err, user) {
+          if (err || !user) return done('Invalid Conversation')
+
+          return done(null, user, convo)
+        })
+      },
+      function (user, convo, done) {
+        const Message = new MessageSchema({
           conversation: convo._id,
-          owner: owner,
+          owner: user._id,
           body: message
         })
 

programming_language: JavaScript
filename: messages.js
change_type: ModificationType.MODIFY
diff: @@ -23,41 +23,34 @@ define('pages/messages', [
   'history',
   'isinview'
 ], function ($, _, angular, UIKit, moment, helpers) {
-  var messagesPage = {}
+  const messagesPage = {}
 
   messagesPage.init = function (callback) {
     $(document).ready(function () {
-      var $messageScroller = $('#message-content.scrollable')
-
-      var $messagesWrapper = $('#messages')
-
-      var $scrollspy = $('#conversation-scrollspy')
-
-      var $spinner = $scrollspy.find('i')
-
-      var $searchBox = $('.search-box').find('input')
-
-      var $nextPage = 2
-
-      var $enabled = true
-
-      var $loading = false
-
+      const $messageScroller = $('#message-content.scrollable')
+      const $messagesWrapper = $('#messages')
+      const $scrollspy = $('#conversation-scrollspy')
+      const $spinner = $scrollspy.find('i')
+      const $searchBox = $('.search-box').find('input')
+      let $nextPage = 2
+      let $enabled = true
+      let $loading = false
       // $inview             = null,
+      const $recentMessages = {}
+      const $convoId = $('#message-content[data-conversation-id]').attr('data-conversation-id')
+      const $loggedInAccountId = window.trudeskSessionService.getUser()._id
 
-      var $recentMessages = {}
-
-      var $convoId = $('#message-content[data-conversation-id]').attr('data-conversation-id')
-
-      var $loggedInAccountId = window.trudeskSessionService.getUser()._id
+      setTimeout(function () {
+        $('script#preloader').remove()
+      }, 1000)
 
       // Setup Context Menu
       helpers.setupContextMenu('#convo-list > ul > li', function (action, target) {
-        var $li = $(target)
+        let $li = $(target)
         if (!$li.is('li')) {
           $li = $(target).parents('li')
         }
-        var convoId = $li.attr('data-conversation-id')
+        const convoId = $li.attr('data-conversation-id')
         if (action.toLowerCase() === 'delete') {
           UIKit.modal.confirm(
             'Are you sure you want to delete this conversation?',
@@ -87,7 +80,7 @@ define('pages/messages', [
 
         // set active
         if ($convoId !== undefined) {
-          var item = $('ul > li[data-conversation-id="' + $convoId + '"]')
+          const item = $('ul > li[data-conversation-id="' + $convoId + '"]')
           item.addClass('active')
         }
 
@@ -98,7 +91,7 @@ define('pages/messages', [
             .toLowerCase() === 'messages'
         ) {
           $('.chat-box-position').each(function () {
-            var self = $(this)
+            const self = $(this)
             self.remove()
           })
 
@@ -108,7 +101,7 @@ define('pages/messages', [
 
           $messageScroller.scroll(function () {
             if ($scrollspy.isInView($messageScroller)) {
-              var run = _.throttle(loadMoreMessages, 100)
+              const run = _.throttle(loadMoreMessages, 100)
               run()
             }
           })
@@ -122,11 +115,11 @@ define('pages/messages', [
           success: function (response) {
             if (response.success) {
               // Check if on conversation
-              var $convo = $('#message-content[data-conversation-id="' + response.conversation._id + '"]')
+              const $convo = $('#message-content[data-conversation-id="' + response.conversation._id + '"]')
               if ($convo.length > 0) {
                 History.pushState(null, null, '/messages', false)
               } else {
-                var $convoLI = $('#convo-list').find('li[data-conversation-id="' + response.conversation._id + '"]')
+                const $convoLI = $('#convo-list').find('li[data-conversation-id="' + response.conversation._id + '"]')
                 if ($convoLI.length > 0) {
                   $convoLI.remove()
                 }
@@ -146,7 +139,7 @@ define('pages/messages', [
       }
 
       function onSearchKeyUp () {
-        var searchTerm = $searchBox.val().toLowerCase()
+        const searchTerm = $searchBox.val().toLowerCase()
         $('.all-user-list li').each(function () {
           if ($(this).filter('[data-search-term *= ' + searchTerm + ']').length > 0 || searchTerm.length < 1) {
             $(this).show()
@@ -168,21 +161,21 @@ define('pages/messages', [
         })
           .done(function (data) {
             $spinner.addClass('uk-hidden')
-            var messages = data.messages
+            const messages = data.messages
             if (_.size(messages) < 1) {
               $enabled = false
               $loading = false
               return false
             }
 
-            var html = ''
+            let html = ''
 
             _.each(messages, function (m) {
-              var h = buildMessageHTML(m)
+              const h = buildMessageHTML(m)
               if (h.length > 0) html += h
             })
 
-            var stage = $('<div></div>')
+            const stage = $('<div></div>')
               .appendTo('body')
               .addClass('stage')
               .css({
@@ -193,7 +186,7 @@ define('pages/messages', [
                 left: '-9999em'
               })
               .append(html)
-            var height = $(stage).outerHeight()
+            const height = $(stage).outerHeight()
             $(stage).remove()
 
             $messagesWrapper.prepend(html)
@@ -210,15 +203,15 @@ define('pages/messages', [
       }
 
       function buildMessageHTML (message) {
-        var html = ''
-        var loggedInAccountId = window.trudeskSessionService.getUser()._id
+        let html = ''
+        const loggedInAccountId = window.trudeskSessionService.getUser()._id
         if (loggedInAccountId === undefined) return false
-        var left = true
+        let left = true
         if (message.owner._id.toString() === loggedInAccountId.toString()) {
           left = false
         }
 
-        var image = message.owner.image === undefined ? 'defaultProfile.jpg' : message.owner.image
+        const image = message.owner.image === undefined ? 'defaultProfile.jpg' : message.owner.image
 
         if (left) {
           html += '<div class="message message-left">'
@@ -259,7 +252,7 @@ define('pages/messages', [
 
       // On user Typing
       $(window).on('$trudesk:chat:typing.conversation', function (event, data) {
-        var convoListItem = $('#convo-list').find('li[data-conversation-id="' + data.cid + '"]')
+        const convoListItem = $('#convo-list').find('li[data-conversation-id="' + data.cid + '"]')
         if (convoListItem.length > 0) {
           $recentMessages[data.cid] = convoListItem.find('.message-subject').text()
           convoListItem.find('.message-subject').text(data.fromUser.fullname + ' is typing...')
@@ -267,7 +260,7 @@ define('pages/messages', [
       })
 
       $(window).on('$trudesk:chat:stoptyping.conversation', function (event, data) {
-        var convoListItem = $('#convo-list').find('li[data-conversation-id="' + data.cid + '"]')
+        const convoListItem = $('#convo-list').find('li[data-conversation-id="' + data.cid + '"]')
         if (convoListItem.length > 0) {
           convoListItem.find('.message-subject').text($recentMessages[data.cid])
         }
@@ -275,38 +268,38 @@ define('pages/messages', [
 
       // On Chat Message
       $(window).on('$trudesk:chat:message.conversation', function (event, data) {
-        var message = {
+        const message = {
           _id: data.messageId,
           conversation: data.conversation,
           body: data.message,
           owner: data.fromUser
         }
 
-        var html = buildMessageHTML(message)
-        var messageWrapper = $('#message-content[data-conversation-id="' + message.conversation + '"]')
+        const html = buildMessageHTML(message)
+        const messageWrapper = $('#message-content[data-conversation-id="' + message.conversation + '"]')
         if (messageWrapper.length > 0) {
           messageWrapper.find('#messages').append(html)
         }
 
-        var convoListItem = $('li[data-conversation-id="' + data.conversation + '"]')
+        const convoListItem = $('li[data-conversation-id="' + data.conversation + '"]')
         if (convoListItem.length > 0) {
           convoListItem.attr('data-updatedAt', new Date())
-          var ul = convoListItem.parent('ul')
-          var li = ul.children('li')
+          const ul = convoListItem.parent('ul')
+          const li = ul.children('li')
           li.detach().sort(function (a, b) {
             return new Date($(a).attr('data-updatedAt')) < new Date($(b).attr('data-updatedAt'))
           })
 
           ul.append(li)
 
-          var fromName = message.owner.fullname
+          let fromName = message.owner.fullname
           if (message.owner._id.toString() === $loggedInAccountId) {
             fromName = 'You'
           }
 
           convoListItem.find('.message-subject').text(fromName + ': ' + message.body)
           $recentMessages[message.conversation] = fromName + ': ' + message.body
-          var timezone = helpers.getTimezone()
+          const timezone = helpers.getTimezone()
           convoListItem.find('.message-date').text(
             moment
               .utc()
@@ -314,25 +307,25 @@ define('pages/messages', [
               .calendar()
           )
         } else {
-          var convoUL = $('#convo-list > ul.message-items')
+          const convoUL = $('#convo-list > ul.message-items')
           if (convoUL.length > 0) {
-            var partner = message.owner
+            let partner = message.owner
             if (message.owner._id.toString() === $loggedInAccountId.toString()) {
               partner = data.toUser
             }
-            var newLI = buildConversationListItem({
+            const newLI = buildConversationListItem({
               _id: message.conversation,
               partner: partner,
               updatedAt: new Date(),
               recentMessage: message.owner.fullname + ': ' + message.body
             })
 
-            var $injector = angular.injector(['ng', 'trudesk'])
+            const $injector = angular.injector(['ng', 'trudesk'])
             $injector.invoke([
               '$compile',
               '$rootScope',
               function ($compile, $rootScope) {
-                var $scope = convoUL.prepend(newLI).scope()
+                const $scope = convoUL.prepend(newLI).scope()
                 $compile(convoUL)($scope || $rootScope)
                 $rootScope.$digest()
               }
@@ -345,7 +338,7 @@ define('pages/messages', [
       })
 
       function buildConversationListItem (data) {
-        var html = ''
+        let html = ''
 
         html +=
           '<li ng-click="loadConversation(\'' +
@@ -356,7 +349,7 @@ define('pages/messages', [
           data.updatedAt +
           '">'
         html += '<div class="profile-pic">'
-        var imageUrl = 'defaultProfile.jpg'
+        let imageUrl = 'defaultProfile.jpg'
         if (data.partner.image) {
           imageUrl = data.partner.image
         }

programming_language: JavaScript