diff --git a/lib/models/campaigns.js b/lib/models/campaigns.js index b71d1bbf..98a2a896 100644 --- a/lib/models/campaigns.js +++ b/lib/models/campaigns.js @@ -619,6 +619,9 @@ module.exports.create = (campaign, opts, callback) => { Object.keys(campaign).forEach(key => { let value = typeof campaign[key] === 'number' ? campaign[key] : (campaign[key] || '').toString().trim(); key = tools.toDbKey(key); + if (key === 'description') { + value = tools.purifyHTML(value); + } if (allowedKeys.indexOf(key) >= 0 && keys.indexOf(key) < 0) { keys.push(key); values.push(value); @@ -791,6 +794,9 @@ module.exports.update = (id, updates, callback) => { Object.keys(campaign).forEach(key => { let value = typeof campaign[key] === 'number' ? campaign[key] : (campaign[key] || '').toString().trim(); key = tools.toDbKey(key); + if (key === 'description') { + value = tools.purifyHTML(value); + } if (allowedKeys.indexOf(key) >= 0 && keys.indexOf(key) < 0) { keys.push(key); values.push(value); diff --git a/lib/models/lists.js b/lib/models/lists.js index 4d58952c..97db2210 100644 --- a/lib/models/lists.js +++ b/lib/models/lists.js @@ -123,6 +123,9 @@ module.exports.create = (list, callback) => { Object.keys(list).forEach(key => { let value = list[key].trim(); key = tools.toDbKey(key); + if (key === 'description') { + value = tools.purifyHTML(value); + } if (allowedKeys.indexOf(key) >= 0) { keys.push(key); values.push(value); @@ -182,6 +185,9 @@ module.exports.update = (id, updates, callback) => { Object.keys(updates).forEach(key => { let value = updates[key].trim(); key = tools.toDbKey(key); + if (key === 'description') { + value = tools.purifyHTML(value); + } if (allowedKeys.indexOf(key) >= 0) { keys.push(key); values.push(value); diff --git a/lib/models/templates.js b/lib/models/templates.js index 0753a87f..4171ebb1 100644 --- a/lib/models/templates.js +++ b/lib/models/templates.js @@ -88,6 +88,9 @@ module.exports.create = (template, callback) => { Object.keys(template).forEach(key => { let value = template[key].trim(); key = tools.toDbKey(key); + if (key === 'description') { + value = tools.purifyHTML(value); + } if (allowedKeys.indexOf(key) >= 0) { keys.push(key); values.push(value); @@ -133,6 +136,9 @@ module.exports.update = (id, updates, callback) => { Object.keys(updates).forEach(key => { let value = updates[key].trim(); key = tools.toDbKey(key); + if (key === 'description') { + value = tools.purifyHTML(value); + } if (allowedKeys.indexOf(key) >= 0) { keys.push(key); values.push(value); diff --git a/lib/tools.js b/lib/tools.js index 6dbf3a44..e80b8d4a 100644 --- a/lib/tools.js +++ b/lib/tools.js @@ -9,6 +9,7 @@ let jsdom = require('jsdom'); let he = require('he'); let _ = require('./translate')._; let util = require('util'); +let createDOMPurify = require('dompurify'); let blockedUsers = ['abuse', 'admin', 'billing', 'compliance', 'devnull', 'dns', 'ftp', 'hostmaster', 'inoc', 'ispfeedback', 'ispsupport', 'listrequest', 'list', 'maildaemon', 'noc', 'noreply', 'noreply', 'null', 'phish', 'phishing', 'postmaster', 'privacy', 'registrar', 'root', 'security', 'spam', 'support', 'sysadmin', 'tech', 'undisclosedrecipients', 'unsubscribe', 'usenet', 'uucp', 'webmaster', 'www']; @@ -23,6 +24,7 @@ module.exports = { formatMessage, getMessageLinks, prepareHtml, + purifyHTML, workers: new Set() }; @@ -232,3 +234,14 @@ function prepareHtml(html, callback) { return callback(null, juice(preparedHtml)); }); } + +function purifyHTML(html) { + let win = jsdom.jsdom('', { + features: { + FetchExternalResources: false, // disables resource loading over HTTP / filesystem + ProcessExternalResources: false // do not execute JS within script blocks + } + }).defaultView; + let DOMPurify = createDOMPurify(win); + return DOMPurify.sanitize(html); +} diff --git a/package.json b/package.json index b6db168b..f60bb525 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "csurf": "^1.9.0", "csv-generate": "^1.0.0", "csv-parse": "^1.2.0", + "dompurify": "^0.8.5", "escape-html": "^1.0.3", "express": "^4.15.2", "express-session": "^1.15.1",