- Fix critical and moderate security vulnerabilities reported at 2020-02-26 with

responsible disclosure by [Dejan Zelic](https://twitter.com/dejandayoff),
  Justin Benjamin and others at [Offensive Security](https://twitter.com/offsectraining),
  that follow standard 90 days before public disclosure.
  Thanks to xet7.
- Fix webhook error that prevented some card etc deleting from web UI of board.
  Thanks to xet7.
- Add some more Font Awesome icons.
  Thanks to xet7.
- Remove autofocus from many form input boxes so that they would not cause warnings.
  Thanks to xet7.
This commit is contained in:
Lauri Ojansivu 2020-03-01 20:59:53 +02:00
parent fc35c234a7
commit aac7c380c8
6 changed files with 368 additions and 338 deletions

View file

@ -110,7 +110,7 @@ template(name="editUserPopup")
label.hide.userId(type="text" value=user._id) label.hide.userId(type="text" value=user._id)
label label
| {{_ 'fullname'}} | {{_ 'fullname'}}
input.js-profile-fullname(type="text" value=user.profile.fullname autofocus) input.js-profile-fullname(type="text" value=user.profile.fullname)
label label
| {{_ 'username'}} | {{_ 'username'}}
span.error.hide.username-taken span.error.hide.username-taken
@ -159,7 +159,7 @@ template(name="newUserPopup")
//label.hide.userId(type="text" value=user._id) //label.hide.userId(type="text" value=user._id)
label label
| {{_ 'fullname'}} | {{_ 'fullname'}}
input.js-profile-fullname(type="text" value="" autofocus) input.js-profile-fullname(type="text" value="")
label label
| {{_ 'username'}} | {{_ 'username'}}
span.error.hide.username-taken span.error.hide.username-taken

View file

@ -245,7 +245,7 @@ template(name="outgoingWebhooksPopup")
b   b  
.materialCheckBox(class="{{#unless enabled}}is-checked{{/unless}}") .materialCheckBox(class="{{#unless enabled}}is-checked{{/unless}}")
input.js-outgoing-webhooks-title(placeholder="{{_ 'webhook-title'}}" type="text" name="title" value=title) input.js-outgoing-webhooks-title(placeholder="{{_ 'webhook-title'}}" type="text" name="title" value=title)
input.js-outgoing-webhooks-url(type="text" name="url" value=url autofocus) input.js-outgoing-webhooks-url(type="text" name="url" value=url)
input.js-outgoing-webhooks-token(placeholder="{{_ 'webhook-token' }}" type="text" value=token name="token") input.js-outgoing-webhooks-token(placeholder="{{_ 'webhook-token' }}" type="text" value=token name="token")
select.js-outgoing-webhooks-type(name="type") select.js-outgoing-webhooks-type(name="type")
each _type in types each _type in types
@ -257,7 +257,7 @@ template(name="outgoingWebhooksPopup")
input(type="hidden" value=_id name="id") input(type="hidden" value=_id name="id")
input.primary.wide(type="submit" value="{{_ 'save'}}") input.primary.wide(type="submit" value="{{_ 'save'}}")
form.integration-form form.integration-form
input.js-outgoing-webhooks-title(placeholder="{{_ 'webhook-title'}}" type="text" name="title" autofocus) input.js-outgoing-webhooks-title(placeholder="{{_ 'webhook-title'}}" type="text" name="title")
input.js-outgoing-webhooks-url(placeholder="{{_ 'URL' }}" type="text" name="url") input.js-outgoing-webhooks-url(placeholder="{{_ 'URL' }}" type="text" name="url")
input.js-outgoing-webhooks-token(placeholder="{{_ 'webhook-token' }}" type="text" name="token") input.js-outgoing-webhooks-token(placeholder="{{_ 'webhook-token' }}" type="text" name="token")
select.js-outgoing-webhooks-type(name="type") select.js-outgoing-webhooks-type(name="type")
@ -267,7 +267,10 @@ template(name="outgoingWebhooksPopup")
template(name="boardMenuPopup") template(name="boardMenuPopup")
ul.pop-over-list ul.pop-over-list
li: a.js-custom-fields {{_ 'custom-fields'}} li
a.js-custom-fields
i.fa.fa-list-alt
| {{_ 'custom-fields'}}
li li
a.js-open-archives a.js-open-archives
i.fa.fa-archive i.fa.fa-archive

View file

@ -108,7 +108,7 @@ if (Meteor.isServer) {
let participants = []; let participants = [];
let watchers = []; let watchers = [];
let title = 'act-activity-notify'; let title = 'act-activity-notify';
let board = null; const board = Boards.findOne(activity.boardId);
const description = `act-${activity.activityType}`; const description = `act-${activity.activityType}`;
const params = { const params = {
activityId: activity._id, activityId: activity._id,
@ -122,8 +122,11 @@ if (Meteor.isServer) {
params.userId = activity.userId; params.userId = activity.userId;
} }
if (activity.boardId) { if (activity.boardId) {
board = activity.board(); if (board.title.length > 0) {
params.board = board.title; params.board = board.title;
} else {
params.board = '';
}
title = 'act-withBoardTitle'; title = 'act-withBoardTitle';
params.url = board.absoluteUrl(); params.url = board.absoluteUrl();
params.boardId = activity.boardId; params.boardId = activity.boardId;

View file

@ -619,9 +619,33 @@ Users.mutations({
}, },
}); });
Meteor.methods({
setListSortBy(value) {
check(value, String);
Meteor.user().setListSortBy(value);
},
toggleDesktopDragHandles() {
const user = Meteor.user();
user.toggleDesktopHandles(user.hasShowDesktopDragHandles());
},
toggleSystemMessages() {
const user = Meteor.user();
user.toggleSystem(user.hasHiddenSystemMessages());
},
toggleMinicardLabelText() {
const user = Meteor.user();
user.toggleLabelText(user.hasHiddenMinicardLabelText());
},
changeLimitToShowCardsCount(limit) {
check(limit, Number);
Meteor.user().setShowCardsCountAt(limit);
},
});
if (Meteor.isServer) {
Meteor.methods({ Meteor.methods({
setCreateUser(fullname, username, password, isAdmin, isActive, email) { setCreateUser(fullname, username, password, isAdmin, isActive, email) {
if (Meteor.user().isAdmin) { if (Meteor.user() && Meteor.user().isAdmin) {
check(fullname, String); check(fullname, String);
check(username, String); check(username, String);
check(password, String); check(password, String);
@ -649,6 +673,7 @@ Meteor.methods({
} }
}, },
setUsername(username, userId) { setUsername(username, userId) {
if (Meteor.user() && Meteor.user().isAdmin) {
check(username, String); check(username, String);
check(userId, String); check(userId, String);
const nUsersWithUsername = Users.find({ username }).count(); const nUsersWithUsername = Users.find({ username }).count();
@ -657,28 +682,10 @@ Meteor.methods({
} else { } else {
Users.update(userId, { $set: { username } }); Users.update(userId, { $set: { username } });
} }
}, }
setListSortBy(value) {
check(value, String);
Meteor.user().setListSortBy(value);
},
toggleDesktopDragHandles() {
const user = Meteor.user();
user.toggleDesktopHandles(user.hasShowDesktopDragHandles());
},
toggleSystemMessages() {
const user = Meteor.user();
user.toggleSystem(user.hasHiddenSystemMessages());
},
toggleMinicardLabelText() {
const user = Meteor.user();
user.toggleLabelText(user.hasHiddenMinicardLabelText());
},
changeLimitToShowCardsCount(limit) {
check(limit, Number);
Meteor.user().setShowCardsCountAt(limit);
}, },
setEmail(email, userId) { setEmail(email, userId) {
if (Meteor.user() && Meteor.user().isAdmin) {
if (Array.isArray(email)) { if (Array.isArray(email)) {
email = email.shift(); email = email.shift();
} }
@ -701,8 +708,10 @@ Meteor.methods({
}, },
}); });
} }
}
}, },
setUsernameAndEmail(username, email, userId) { setUsernameAndEmail(username, email, userId) {
if (Meteor.user() && Meteor.user().isAdmin) {
check(username, String); check(username, String);
if (Array.isArray(email)) { if (Array.isArray(email)) {
email = email.shift(); email = email.shift();
@ -711,18 +720,17 @@ Meteor.methods({
check(userId, String); check(userId, String);
Meteor.call('setUsername', username, userId); Meteor.call('setUsername', username, userId);
Meteor.call('setEmail', email, userId); Meteor.call('setEmail', email, userId);
}
}, },
setPassword(newPassword, userId) { setPassword(newPassword, userId) {
if (Meteor.user() && Meteor.user().isAdmin) {
check(userId, String); check(userId, String);
check(newPassword, String); check(newPassword, String);
if (Meteor.user().isAdmin) { if (Meteor.user().isAdmin) {
Accounts.setPassword(userId, newPassword); Accounts.setPassword(userId, newPassword);
} }
}
}, },
});
if (Meteor.isServer) {
Meteor.methods({
// we accept userId, username, email // we accept userId, username, email
inviteUserToBoard(username, boardId) { inviteUserToBoard(username, boardId) {
check(username, String); check(username, String);
@ -754,8 +762,9 @@ if (Meteor.isServer) {
throw new Meteor.Error('error-user-notAllowSelf'); throw new Meteor.Error('error-user-notAllowSelf');
} else { } else {
if (posAt <= 0) throw new Meteor.Error('error-user-doesNotExist'); if (posAt <= 0) throw new Meteor.Error('error-user-doesNotExist');
if (Settings.findOne().disableRegistration) if (Settings.findOne({ disableRegistration: true })) {
throw new Meteor.Error('error-user-notCreated'); throw new Meteor.Error('error-user-notCreated');
}
// Set in lowercase email before creating account // Set in lowercase email before creating account
const email = username.toLowerCase(); const email = username.toLowerCase();
username = email.substring(0, posAt); username = email.substring(0, posAt);

View file

@ -1,3 +1,4 @@
if (Meteor.isServer) {
const postCatchError = Meteor.wrapAsync((url, options, resolve) => { const postCatchError = Meteor.wrapAsync((url, options, resolve) => {
HTTP.post(url, options, (err, res) => { HTTP.post(url, options, (err, res) => {
if (err) { if (err) {
@ -100,6 +101,7 @@ const responseFunc = data => {
}; };
Meteor.methods({ Meteor.methods({
outgoingWebhooks(integration, description, params) { outgoingWebhooks(integration, description, params) {
if (Meteor.user()) {
check(integration, Object); check(integration, Object);
check(description, String); check(description, String);
check(params, Object); check(params, Object);
@ -153,7 +155,11 @@ Meteor.methods({
headers, headers,
data: is2way ? { description, ...clonedParams } : value, data: is2way ? { description, ...clonedParams } : value,
}; };
if (!Integrations.findOne({ url: integration.url })) return;
const url = integration.url; const url = integration.url;
if (is2way) { if (is2way) {
const cid = params.commentId; const cid = params.commentId;
const comment = params.comment; const comment = params.comment;
@ -187,6 +193,7 @@ Meteor.methods({
} else { } else {
throw new Meteor.Error('error-invalid-webhook-response'); throw new Meteor.Error('error-invalid-webhook-response');
} }
//}); }
}, },
}); });
}

View file

@ -1,7 +1,9 @@
import { MongoInternals } from 'meteor/mongo'; import { MongoInternals } from 'meteor/mongo';
if (Meteor.isServer) {
Meteor.methods({ Meteor.methods({
getStatistics() { getStatistics() {
if (Meteor.user() && Meteor.user().isAdmin) {
const os = require('os'); const os = require('os');
const pjson = require('/package.json'); const pjson = require('/package.json');
const statistics = {}; const statistics = {};
@ -50,7 +52,9 @@ Meteor.methods({
mongoOplogEnabled = oplogEnabled; mongoOplogEnabled = oplogEnabled;
} catch (e) { } catch (e) {
try { try {
const { version } = Promise.await(mongo.db.command({ buildinfo: 1 })); const { version } = Promise.await(
mongo.db.command({ buildinfo: 1 }),
);
mongoVersion = version; mongoVersion = version;
mongoStorageEngine = 'unknown'; mongoStorageEngine = 'unknown';
} catch (e) { } catch (e) {
@ -64,5 +68,9 @@ Meteor.methods({
mongoOplogEnabled, mongoOplogEnabled,
}; };
return statistics; return statistics;
} else {
return false;
}
}, },
}); });
}