Improved HTML escaping.

Ylian Saint-Hilaire committed Jun 26, 2020 at 18:04 UTC 36b5831f1861fa413b2f5925f5190c46f366af9b
5 files changed +34 -26
meshuser.js
+8 -8
@@ -4279,7 +4279,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4279 }
4280 case 'distributeCore': {
4281 // This is only available when plugins are enabled since it could cause stress on the server
4282 - if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin with plugins enabled
4282 + if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
4283 for (var i in command.nodes) {
4284 parent.sendMeshAgentCore(user, domain, command.nodes[i]._id, 'default');
4285 }
@@ -4287,14 +4287,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4287 }
4288 case 'plugins': {
4289 // Since plugin actions generally require a server restart, use the Full admin permission
4290 - if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin with plugins enabled
4290 + if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
4291 parent.db.getPlugins(function(err, docs) {
4292 try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
4293 });
4294 break;
4295 }
4296 case 'pluginLatestCheck': {
4297 - if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin with plugins enabled
4297 + if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
4298 parent.parent.pluginHandler.getPluginLatest()
4299 .then(function(latest) {
4300 try { ws.send(JSON.stringify({ action: 'pluginVersionsAvailable', list: latest })); } catch (ex) { }
@@ -4302,7 +4302,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4302 break;
4303 }
4304 case 'addplugin': {
4305 - if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin, plugins enabled
4305 + if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
4306 try {
4307 parent.parent.pluginHandler.getPluginConfig(command.url)
4308 .then(parent.parent.pluginHandler.addPlugin)
@@ -4319,7 +4319,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4319 break;
4320 }
4321 case 'installplugin': {
4322 - if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin, plugins enabled
4322 + if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
4323 parent.parent.pluginHandler.installPlugin(command.id, command.version_only, null, function(){
4324 parent.db.getPlugins(function(err, docs) {
4325 try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
@@ -4330,7 +4330,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4330 break;
4331 }
4332 case 'disableplugin': {
4333 - if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin, plugins enabled
4333 + if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
4334 parent.parent.pluginHandler.disablePlugin(command.id, function(){
4335 parent.db.getPlugins(function(err, docs) {
4336 try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
@@ -4341,7 +4341,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4341 break;
4342 }
4343 case 'removeplugin': {
4344 - if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin, plugins enabled
4344 + if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
4345 parent.parent.pluginHandler.removePlugin(command.id, function(){
4346 parent.db.getPlugins(function(err, docs) {
4347 try { ws.send(JSON.stringify({ action: 'updatePluginList', list: docs, result: err })); } catch (ex) { }
@@ -4350,7 +4350,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
4350 break;
4351 }
4352 case 'getpluginversions': {
4353 - if ((user.siteadmin & 0xFFFFFFFF) == 0 || parent.parent.pluginHandler == null) break; // must be full admin, plugins enabled
4353 + if ((user.siteadmin != 0xFFFFFFFF) || (parent.parent.pluginHandler == null)) break; // Must be full admin with plugins enabled
4354 parent.parent.pluginHandler.getPluginVersions(command.id)
4355 .then(function (versionInfo) {
4356 try { ws.send(JSON.stringify({ action: 'downgradePluginVersions', info: versionInfo, error: null })); } catch (ex) { }
translate/translate.json
+7
@@ -297,6 +297,13 @@
297 "default.handlebars->27->171"
298 ]
299 },
300 + {
301 + "en": "'",
302 + "xloc": [
303 + "agentinvite.handlebars->3->4",
304 + "agentinvite.handlebars->3->5"
305 + ]
306 + },
307 {
308 "cs": "(",
309 "de": "(",
views/agentinvite.handlebars
+3 -2
@@ -144,7 +144,7 @@
144 var installFlags = '{{{installflags}}}';
145 var groupName = decodeURIComponent('{{{meshname}}}');
146 if (groupName != '') {
147 - QH('groupname', format("Remote Agent Installation for {0}", groupName));
147 + QH('groupname', format("Remote Agent Installation for {0}", escapeHtml(groupName)));
148 document.title = format("{0} - Agent Installation", groupName);
149 } else {
150 document.title = "Agent Installation";
@@ -295,7 +295,8 @@
295 function copyToClipLinuxUnInstall() { copyTextToClip(linuxUnInstall); }
296 function copyTextToClip(txt) { function selectElementText(e) { if (document.selection) { var range = document.body.createTextRange(); range.moveToElementText(e); range.select(); } else if (window.getSelection) { var range = document.createRange(); range.selectNode(e); window.getSelection().removeAllRanges(); window.getSelection().addRange(range); } } var e = document.createElement('DIV'); e.textContent = txt; document.body.appendChild(e); selectElementText(e); document.execCommand('copy'); e.remove(); }
297 function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
298 -
298 + function escapeHtml(string) { return String(string).replace(/[&<>"'`=\/]/g, function (s) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;', '/': '&#x2F;', '`': '&#x60;', '=': '&#x3D;' }[s]; }); };
299 + function escapeHtmlBreaks(string) { return String(string).replace(/[&<>"'`=\/]/g, function (s) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;', '/': '&#x2F;', '`': '&#x60;', '=': '&#x3D;', '\r': '<br />', '\n': '' }[s]; }); };
300 </script>
301 </body>
302 </html>
views/default-mobile.handlebars
+4 -4
@@ -733,7 +733,7 @@
733 var webState = '{{{webstate}}}';
734 if (webState != '') { webState = JSON.parse(decodeURIComponent(webState)); }
735 for (var i in webState) { localStorage.setItem(i, webState[i]); }
736 - if (!webState.loctag) { delete localStorage.removeItem('loctag'); }
736 + if (webState && !webState.loctag) { delete localStorage.removeItem('loctag'); }
737
738 var urlargs = parseUriArgs();
739 if (urlargs.key && (isAlphaNumeric(urlargs.key) == false)) { delete urlargs.key; }
@@ -1714,7 +1714,7 @@
1714 if (filetreelinkpath != '') { filetreelinkpath += '/' + filetreelocation[i]; if (folderdepth > 2) { publicPath += '/' + filetreelocation[i]; } }
1715 }
1716 filetreex = filetreex.f[filetreelocation[i]];
1717 - displayPath += ' / <a style=cursor:pointer onclick=p5folderup(' + folderdepth + ')>' + (filetreex.n != null ? filetreex.n : filetreelocation[i]) + '</a>';
1717 + displayPath += ' / <a style=cursor:pointer onclick=p5folderup(' + folderdepth + ')>' + EscapeHtml(filetreex.n != null ? filetreex.n : filetreelocation[i]) + '</a>';
1718 folderdepth++;
1719 } else {
1720 break;
@@ -2435,7 +2435,7 @@
2435
2436 // Node tags
2437 var groupingTags = '<i>' + "None" + '</i>';
2438 - if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span style="background-color:lightgray;padding:3px;margin-right:4px;border-radius:5px">' + node.tags[i] + '</span>'; } }
2438 + if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span style="background-color:lightgray;padding:3px;margin-right:4px;border-radius:5px">' + EscapeHtml(node.tags[i]) + '</span>'; } }
2439 if ((meshrights & 4) != 0) {
2440 x += addDeviceAttribute("Tags", '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + '</span>');
2441 } else {
@@ -3224,7 +3224,7 @@
3224 var x = p13filetree.path.split('\\');
3225 p13filetreelocation = [];
3226 for (var i in x) { if (x[i] != '') { p13filetreelocation.push(x[i]); } } // Remove empty spaces
3227 - for (var i in p13filetreelocation) { displayPath += ' / <a style=cursor:pointer onclick=p13folderup(' + (parseInt(i) + 1) + ')>' + p13filetreelocation[i] + '</a>' } // Setup the path we display
3227 + for (var i in p13filetreelocation) { displayPath += ' / <a style=cursor:pointer onclick=p13folderup(' + (parseInt(i) + 1) + ')>' + EscapeHtml(p13filetreelocation[i]) + '</a>' } // Setup the path we display
3228 var newlinkpath = p13filetreelocation.join('/');
3229
3230 // Sort the files
views/default.handlebars
+12 -12
@@ -5352,12 +5352,12 @@
5352 if ((node.agent != null) && (node.agent.tag != null)) {
5353 // Attribute: Mesh Agent Tag
5354 var tag = EscapeHtml(node.agent.tag);
5355 - if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
5355 + if (tag.startsWith('mailto:')) { tag = '<a href="' + EscapeHtml(tag) + '">' + EscapeHtml(tag.substring(7)) + '</a>'; }
5356 x += addDeviceAttribute("Agent Tag", tag);
5357 } else if ((node.intelamt != null) && (node.intelamt.tag != null)) {
5358 // Attribute: Intel AMT Tag
5359 var tag = EscapeHtml(node.intelamt.tag);
5360 - if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
5360 + if (tag.startsWith('mailto:')) { tag = '<a href="' + EscapeHtml(tag) + '">' + EscapeHtml(tag.substring(7)) + '</a>'; }
5361 x += addDeviceAttribute("Intel&reg; AMT Tag", tag);
5362 }
5363
@@ -5416,7 +5416,7 @@
5416
5417 // Node grouping tags
5418 var groupingTags = '<i>' + "None" + '</i>';
5419 - if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span class="tagSpan">' + node.tags[i] + '</span>'; } }
5419 + if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span class="tagSpan">' + EscapeHtml(node.tags[i]) + '</span>'; } }
5420 if ((meshrights & 4) != 0) {
5421 x += addDeviceAttribute('Tags', '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + ' <img class=hoverButton src="images/link5.png" /></span>');
5422 } else {
@@ -7522,7 +7522,7 @@
7522 var x = p13filetree.path.split('\\');
7523 p13filetreelocation = [];
7524 for (var i in x) { if (x[i] != '') { p13filetreelocation.push(x[i]); } } // Remove empty spaces
7525 - for (var i in p13filetreelocation) { displayPath += ' / <a href=# style=cursor:pointer onclick="return p13folderup(' + (parseInt(i) + 1) + ')">' + p13filetreelocation[i] + '</a>' } // Setup the path we display
7525 + for (var i in p13filetreelocation) { displayPath += ' / <a href=# style=cursor:pointer onclick="return p13folderup(' + (parseInt(i) + 1) + ')">' + EscapeHtml(p13filetreelocation[i]) + '</a>' } // Setup the path we display
7526 var newlinkpath = p13filetreelocation.join('/');
7527
7528 // Sort the files
@@ -9941,7 +9941,7 @@
9941 if (filetreelinkpath != '') { filetreelinkpath += '/' + filetreelocation[i]; if (folderdepth > 2) { publicPath += '/' + filetreelocation[i]; } }
9942 }
9943 filetreex = filetreex.f[filetreelocation[i]];
9944 - displayPath += ' / <a href=# style=cursor:pointer onclick="return p5folderup(' + folderdepth + ')">' + (filetreex.n != null?filetreex.n:filetreelocation[i]) + '</a>';
9944 + displayPath += ' / <a href=# style=cursor:pointer onclick="return p5folderup(' + folderdepth + ')">' + EscapeHtml(filetreex.n != null?filetreex.n:filetreelocation[i]) + '</a>';
9945 folderdepth++;
9946 } else {
9947 break;
@@ -10446,10 +10446,10 @@
10446 if (user.email != null) {
10447 if (((features & 0x200000) == 0) || (user.email.toLowerCase() != user.name.toLowerCase())) {
10448 // Username & email are different
10449 - username += ', <a href="mailto:' + user.email + '" \'>' + user.email + '</a>' + emailVerified;
10449 + username += ', <a href="mailto:' + EscapeHtml(user.email) + '" \'>' + EscapeHtml(user.email) + '</a>' + emailVerified;
10450 } else {
10451 // Username & email are the same
10452 - username += ' <a href="mailto:' + user.email + '" \'><img src="images/mail12.png" height=9 width=12 title="' + "Send email to user" + '" style="margin-top:2px" /></a>' + emailVerified;
10452 + username += ' <a href="mailto:' + EscapeHtml(user.email) + '" \'><img src="images/mail12.png" height=9 width=12 title="' + "Send email to user" + '" style="margin-top:2px" /></a>' + emailVerified;
10453 }
10454 }
10455
@@ -11314,8 +11314,8 @@
11314 if ((event != null) && (event.originalTarget != null) && (event.originalTarget.href != null)) return;
11315 var user = currentUser = users[decodeURIComponent(userid)];
11316 if (user == null) { setDialogMode(0); go(4); return; }
11317 - QH('p30userName', user.name);
11318 - QH('p31userName', user.name);
11317 + QH('p30userName', EscapeHtml(user.name));
11318 + QH('p31userName', EscapeHtml(user.name));
11319 var self = (user._id == userinfo._id), activeSessions = 0;
11320 if (wssessions != null && wssessions[user._id]) { activeSessions = wssessions[user._id]; }
11321
@@ -11356,9 +11356,9 @@
11356 }
11357
11358 if (((user.siteadmin != 0xFFFFFFFF) || (userinfo.siteadmin == 0xFFFFFFFF))) { // If we are not site admin, we can't change a admin email.
11359 - x += addDeviceAttribute("Email", everify + email + ' <a href="mailto:' + user.email + '" \'><img class=hoverButton src="images/link1.png" /></a>' + ' <img class=hoverButton style=cursor:pointer src="images/link5.png" onclick=p30showUserEmailChangeDialog(event,"' + userid + '") />');
11359 + x += addDeviceAttribute("Email", everify + email + ' <a href="mailto:' + EscapeHtml(user.email) + '" \'><img class=hoverButton src="images/link1.png" /></a>' + ' <img class=hoverButton style=cursor:pointer src="images/link5.png" onclick=p30showUserEmailChangeDialog(event,"' + userid + '") />');
11360 } else {
11361 - x += addDeviceAttribute("Email", everify + email + ' <a href="mailto:' + user.email + '" \'><img class=hoverButton src="images/link1.png" /></a>');
11361 + x += addDeviceAttribute("Email", everify + email + ' <a href="mailto:' + EscapeHtml(user.email) + '" \'><img class=hoverButton src="images/link1.png" /></a>');
11362 }
11363
11364 if ((features & 0x02000000) || (user.phone != null)) { // If SMS is enabled on the server or user has a phone number
@@ -11383,7 +11383,7 @@
11383 // Administrative Realms
11384 if ((userinfo.siteadmin == 0xFFFFFFFF) || (userinfo.siteadmin & 2)) {
11385 var xuserGroups = '<i>' + "None" + '</i>';
11386 - if (user.groups) { xuserGroups = ''; for (var i in user.groups) { xuserGroups += '<span class="tagSpan">' + user.groups[i] + '</span>'; } }
11386 + if (user.groups) { xuserGroups = ''; for (var i in user.groups) { xuserGroups += '<span class="tagSpan">' + EscapeHtml(user.groups[i]) + '</span>'; } }
11387 x += addDeviceAttribute("Admin Realms", addLinkConditional(xuserGroups, 'showUserGroupDialog(event,"' + userid + '")', (userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.groups == null) && (userinfo._id != user._id) && (user.siteadmin != 0xFFFFFFFF))));
11388 }
11389