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 { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', '`': '`', '=': '=' }[s]; }); };
299
+ function escapeHtmlBreaks(string) { return String(string).replace(/[&<>"'`=\/]/g, function (s) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', '`': '`', '=': '=', '\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® 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