From 99c02fb00f1efaf97e1b8a66c56505707e8d7764 Mon Sep 17 00:00:00 2001 From: Chris Brame Date: Sat, 6 Apr 2019 09:23:24 -0400 Subject: [PATCH] fix(tickets): xss fixes --- package.json | 2 +- src/controllers/api/v1/tickets.js | 15 +++++-- src/models/ticket.js | 13 +++--- src/socketio/ticketSocket.js | 3 ++ yarn.lock | 68 ++++++++++++++++++------------- 5 files changed, 62 insertions(+), 39 deletions(-) diff --git a/package.json b/package.json index 2e33bc21f..6dde9d541 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ "redux-saga-thunk": "0.7.3", "request": "2.88.0", "rimraf": "2.6.3", - "sanitize-html": "1.18.4", + "sanitize-html": "1.20.0", "script-loader": "0.7.2", "semver": "5.6.0", "serve-favicon": "2.5.0", diff --git a/src/controllers/api/v1/tickets.js b/src/controllers/api/v1/tickets.js index a8452cde7..56693862c 100644 --- a/src/controllers/api/v1/tickets.js +++ b/src/controllers/api/v1/tickets.js @@ -18,6 +18,7 @@ var moment = require('moment-timezone') var winston = require('winston') var permissions = require('../../../permissions') var emitter = require('../../../emitter') +var sanitizeHtml = require('sanitize-html') var apiTickets = {} @@ -361,9 +362,12 @@ apiTickets.create = function (req, res) { ticket.owner = req.user._id } + ticket.subject = sanitizeHtml(ticket.subject).trim() + var marked = require('marked') var tIssue = ticket.issue tIssue = tIssue.replace(/(\r\n|\n\r|\r|\n)/g, '
') + tIssue = sanitizeHtml(tIssue).trim() ticket.issue = marked(tIssue) ticket.history = [HistoryItem] ticket.subscribers = [req.user._id] @@ -514,8 +518,8 @@ apiTickets.createPublicTicket = function (req, res) { group: group._id, type: ticketType._id, priority: _.first(ticketType.priorities)._id, // TODO: change when priority order is complete! - subject: postData.ticket.subject, - issue: postData.ticket.issue, + subject: sanitizeHtml(postData.ticket.subject).trim(), + issue: sanitizeHtml(postData.ticket.issue).trim(), history: [HistoryItem], subscribers: [savedUser._id] }) @@ -523,6 +527,7 @@ apiTickets.createPublicTicket = function (req, res) { var marked = require('marked') var tIssue = ticket.issue tIssue = tIssue.replace(/(\r\n|\n\r|\r|\n)/g, '
') + tIssue = sanitizeHtml(tIssue).trim() ticket.issue = marked(tIssue) ticket.save(function (err, t) { @@ -647,7 +652,7 @@ apiTickets.update = function (req, res) { }, function (cb) { if (!_.isUndefined(reqTicket.subject)) { - ticket.subject = reqTicket.subject + ticket.subject = sanitizeHtml(reqTicket.subject).trim() } return cb() @@ -679,7 +684,7 @@ apiTickets.update = function (req, res) { }, function (cb) { if (!_.isUndefined(reqTicket.issue) && !_.isNull(reqTicket.issue)) { - ticket.issue = reqTicket.issue + ticket.issue = sanitizeHtml(reqTicket.issue).trim() } return cb() @@ -818,6 +823,8 @@ apiTickets.postComment = function (req, res) { breaks: true }) + comment = sanitizeHtml(comment).trim() + var Comment = { owner: owner, date: new Date(), diff --git a/src/models/ticket.js b/src/models/ticket.js index bb65b6a93..836f86893 100644 --- a/src/models/ticket.js +++ b/src/models/ticket.js @@ -16,6 +16,7 @@ var async = require('async') var mongoose = require('mongoose') var _ = require('lodash') var moment = require('moment') +var sanitizeHtml = require('sanitize-html') // var redisCache = require('../cache/rediscache'); // Needed - For Population @@ -386,7 +387,7 @@ ticketSchema.methods.setTicketDueDate = function (ownerId, dueDate, callback) { */ ticketSchema.methods.setIssue = function (ownerId, issue, callback) { var self = this - self.issue = issue + self.issue = sanitizeHtml(issue).trim() var historyItem = { action: 'ticket:update:issue', description: 'Ticket Issue was updated.', @@ -773,7 +774,7 @@ ticketSchema.statics.getTicketsWithObject = function (grpId, object, callback) { .populate('type tags group') .populate('group.members', 'username fullname email role image title') .populate('group.sendMailTo', 'username fullname email role image title') - .sort('-uid') + .sort({ uid: -1 }) if (limit !== -1) { q.skip(page * limit).limit(limit) @@ -808,7 +809,7 @@ ticketSchema.statics.getTicketsWithObject = function (grpId, object, callback) { } if (!_.isUndefined(object.filter.unassigned)) { - q.where({ assignee: { $exits: false } }) + q.where({ assignee: { $exists: false } }) } if (!_.isUndefined(object.filter.owner)) { @@ -845,15 +846,15 @@ ticketSchema.statics.getTicketsWithObject = function (grpId, object, callback) { ticketSchema.statics.getCountWithObject = function (grpId, object, callback) { if (_.isUndefined(grpId)) { - return callback('Invalid GroupId - TicketSchema.GetTickets()', null) + return callback('Invalid GroupId - TicketSchema.GetCountWithObject()', null) } if (!_.isArray(grpId)) { - return callback('Invalid GroupId (Must be of type Array) - TicketSchema.GetTicketsWithObject()', null) + return callback('Invalid GroupId (Must be of type Array) - TicketSchema.GetCountWithObject()', null) } if (!_.isObject(object)) { - return callback('Invalid Object (Must be of type Object) - TicketSchema.GetTicketsWithObject()', null) + return callback('Invalid Object (Must be of type Object) - TicketSchema.GetCountWithObject()', null) } var self = this diff --git a/src/socketio/ticketSocket.js b/src/socketio/ticketSocket.js index 686071a30..841621dad 100644 --- a/src/socketio/ticketSocket.js +++ b/src/socketio/ticketSocket.js @@ -15,6 +15,7 @@ var _ = require('lodash') var async = require('async') var winston = require('winston') var marked = require('marked') +var sanitizeHtml = require('sanitize-html') var utils = require('../helpers/utils') var emitter = require('../emitter') var ticketSchema = require('../models/ticket') @@ -334,6 +335,8 @@ events.onSetCommentText = function (socket) { breaks: true }) + comment = sanitizeHtml(comment).trim() + var markedComment = marked(comment) ticketSchema.getTicketById(ticketId, function (err, ticket) { diff --git a/yarn.lock b/yarn.lock index 98c6d2f1d..cbfb3f913 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2539,7 +2539,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2, chalk@~2.4.1: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2, chalk@~2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3861,7 +3861,7 @@ domain-browser@^1.1.1: resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== -domelementtype@1, domelementtype@^1.3.0: +domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== @@ -6042,7 +6042,19 @@ htmlparser2@3.8.x: entities "1.0" readable-stream "1.1" -htmlparser2@^3.9.0, htmlparser2@^3.9.1, htmlparser2@^3.9.2: +htmlparser2@^3.10.0: + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + +htmlparser2@^3.9.1, htmlparser2@^3.9.2: version "3.10.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.0.tgz#5f5e422dcf6119c0d983ed36260ce9ded0bee464" integrity sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ== @@ -7128,6 +7140,11 @@ juice@^4.3.2: slick "^1.12.2" web-resource-inliner "^4.2.1" +just-curry-it@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/just-curry-it/-/just-curry-it-3.1.0.tgz#ab59daed308a58b847ada166edd0a2d40766fbc5" + integrity sha512-mjzgSOFzlrurlURaHVjnQodyPNvrHrf1TbQP2XU9NSqBtHQPuHZ+Eb6TAJP7ASeJN9h9K0KXoRTs8u6ouHBKvg== + jwa@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.2.0.tgz#606da70c1c6d425cad329c77c99f2df2a981489a" @@ -7145,11 +7162,6 @@ jws@^3.1.5: jwa "^1.2.0" safe-buffer "^5.0.1" -just-curry-it@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/just-curry-it/-/just-curry-it-3.1.0.tgz#ab59daed308a58b847ada166edd0a2d40766fbc5" - integrity sha512-mjzgSOFzlrurlURaHVjnQodyPNvrHrf1TbQP2XU9NSqBtHQPuHZ+Eb6TAJP7ASeJN9h9K0KXoRTs8u6ouHBKvg== - kareem@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.0.tgz#ef33c42e9024dce511eeaf440cd684f3af1fc769" @@ -7675,7 +7687,7 @@ lodash.merge@^4.4.0, lodash.merge@^4.6.0: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54" integrity sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ== -lodash.mergewith@^4.6.0: +lodash.mergewith@^4.6.0, lodash.mergewith@^4.6.1: version "4.6.1" resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" integrity sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ== @@ -9942,15 +9954,6 @@ postcss-value-parser@^3.3.0, postcss-value-parser@^3.3.1: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== -postcss@^6.0.14: - version "6.0.23" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" - integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== - dependencies: - chalk "^2.4.1" - source-map "^0.6.1" - supports-color "^5.4.0" - postcss@^7.0.5, postcss@^7.0.6: version "7.0.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.14.tgz#4527ed6b1ca0d82c53ce5ec1a2041c2346bbd6e5" @@ -10661,6 +10664,15 @@ readable-stream@3, readable-stream@^3.0.6: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@^3.1.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.3.0.tgz#cb8011aad002eb717bf040291feba8569c986fb9" + integrity sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" @@ -11206,21 +11218,21 @@ safefs@^3.1.2: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sanitize-html@1.18.4: - version "1.18.4" - resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.18.4.tgz#ffdeea13b555dd5e872e9a68b79e5e716cd8c543" - integrity sha512-hjyDYCYrQuhnEjq+5lenLlIfdPBtnZ7z0DkQOC8YGxvkuOInH+1SrkNTj30t4f2/SSv9c5kLniB+uCIpBvYuew== +sanitize-html@1.20.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.20.0.tgz#9a602beb1c9faf960fb31f9890f61911cc4d9156" + integrity sha512-BpxXkBoAG+uKCHjoXFmox6kCSYpnulABoGcZ/R3QyY9ndXbIM5S94eOr1IqnzTG8TnbmXaxWoDDzKC5eJv7fEQ== dependencies: - chalk "^2.3.0" - htmlparser2 "^3.9.0" + chalk "^2.4.1" + htmlparser2 "^3.10.0" lodash.clonedeep "^4.5.0" lodash.escaperegexp "^4.1.2" lodash.isplainobject "^4.0.6" lodash.isstring "^4.0.1" - lodash.mergewith "^4.6.0" - postcss "^6.0.14" + lodash.mergewith "^4.6.1" + postcss "^7.0.5" srcset "^1.0.0" - xtend "^4.0.0" + xtend "^4.0.1" saslprep@^1.0.0: version "1.0.2" @@ -12439,7 +12451,7 @@ supports-color@^3.1.0: dependencies: has-flag "^1.0.0" -supports-color@^5.0.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: +supports-color@^5.0.0, supports-color@^5.2.0, supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==