Skip to content

Commit a1f08c4

Browse files
committed
Fix remote execution bug where email address can contain malicious code
also convert almost all cmd execs for certificates to properly escape arguments
1 parent 54d463a commit a1f08c4

File tree

9 files changed

+316
-236
lines changed

9 files changed

+316
-236
lines changed

backend/internal/access-list.js

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const _ = require('lodash');
2-
const fs = require('fs');
2+
const fs = require('node:fs');
33
const batchflow = require('batchflow');
44
const logger = require('../logger').access;
55
const error = require('../lib/error');
@@ -38,7 +38,7 @@ const internalAccessList = {
3838
.then((row) => {
3939
data.id = row.id;
4040

41-
let promises = [];
41+
const promises = [];
4242

4343
// Now add the items
4444
data.items.map((item) => {
@@ -116,7 +116,7 @@ const internalAccessList = {
116116
.then((row) => {
117117
if (row.id !== data.id) {
118118
// Sanity check that something crazy hasn't happened
119-
throw new error.InternalValidationError('Access List could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
119+
throw new error.InternalValidationError(`Access List could not be updated, IDs do not match: ${row.id} !== ${data.id}`);
120120
}
121121
})
122122
.then(() => {
@@ -135,10 +135,10 @@ const internalAccessList = {
135135
.then(() => {
136136
// Check for items and add/update/remove them
137137
if (typeof data.items !== 'undefined' && data.items) {
138-
let promises = [];
139-
let items_to_keep = [];
138+
const promises = [];
139+
const items_to_keep = [];
140140

141-
data.items.map(function (item) {
141+
data.items.map((item) => {
142142
if (item.password) {
143143
promises.push(accessListAuthModel
144144
.query()
@@ -154,7 +154,7 @@ const internalAccessList = {
154154
}
155155
});
156156

157-
let query = accessListAuthModel
157+
const query = accessListAuthModel
158158
.query()
159159
.delete()
160160
.where('access_list_id', data.id);
@@ -175,9 +175,9 @@ const internalAccessList = {
175175
.then(() => {
176176
// Check for clients and add/update/remove them
177177
if (typeof data.clients !== 'undefined' && data.clients) {
178-
let promises = [];
178+
const promises = [];
179179

180-
data.clients.map(function (client) {
180+
data.clients.map((client) => {
181181
if (client.address) {
182182
promises.push(accessListClientModel
183183
.query()
@@ -190,7 +190,7 @@ const internalAccessList = {
190190
}
191191
});
192192

193-
let query = accessListClientModel
193+
const query = accessListClientModel
194194
.query()
195195
.delete()
196196
.where('access_list_id', data.id);
@@ -249,7 +249,7 @@ const internalAccessList = {
249249

250250
return access.can('access_lists:get', data.id)
251251
.then((access_data) => {
252-
let query = accessListModel
252+
const query = accessListModel
253253
.query()
254254
.select('access_list.*', accessListModel.raw('COUNT(proxy_host.id) as proxy_host_count'))
255255
.leftJoin('proxy_host', function() {
@@ -267,7 +267,7 @@ const internalAccessList = {
267267
}
268268

269269
if (typeof data.expand !== 'undefined' && data.expand !== null) {
270-
query.withGraphFetched('[' + data.expand.join(', ') + ']');
270+
query.withGraphFetched(`[${data.expand.join(', ')}]`);
271271
}
272272

273273
return query.then(utils.omitRow(omissions()));
@@ -327,7 +327,7 @@ const internalAccessList = {
327327
// 3. reconfigure those hosts, then reload nginx
328328

329329
// set the access_list_id to zero for these items
330-
row.proxy_hosts.map(function (val, idx) {
330+
row.proxy_hosts.map((_val, idx) => {
331331
row.proxy_hosts[idx].access_list_id = 0;
332332
});
333333

@@ -340,11 +340,11 @@ const internalAccessList = {
340340
})
341341
.then(() => {
342342
// delete the htpasswd file
343-
let htpasswd_file = internalAccessList.getFilename(row);
343+
const htpasswd_file = internalAccessList.getFilename(row);
344344

345345
try {
346346
fs.unlinkSync(htpasswd_file);
347-
} catch (err) {
347+
} catch (_err) {
348348
// do nothing
349349
}
350350
})
@@ -374,7 +374,7 @@ const internalAccessList = {
374374
getAll: (access, expand, search_query) => {
375375
return access.can('access_lists:list')
376376
.then((access_data) => {
377-
let query = accessListModel
377+
const query = accessListModel
378378
.query()
379379
.select('access_list.*', accessListModel.raw('COUNT(proxy_host.id) as proxy_host_count'))
380380
.leftJoin('proxy_host', function() {
@@ -393,19 +393,19 @@ const internalAccessList = {
393393
// Query is used for searching
394394
if (typeof search_query === 'string') {
395395
query.where(function () {
396-
this.where('name', 'like', '%' + search_query + '%');
396+
this.where('name', 'like', `%${search_query}%`);
397397
});
398398
}
399399

400400
if (typeof expand !== 'undefined' && expand !== null) {
401-
query.withGraphFetched('[' + expand.join(', ') + ']');
401+
query.withGraphFetched(`[${expand.join(', ')}]`);
402402
}
403403

404404
return query.then(utils.omitRows(omissions()));
405405
})
406406
.then((rows) => {
407407
if (rows) {
408-
rows.map(function (row, idx) {
408+
rows.map((row, idx) => {
409409
if (typeof row.items !== 'undefined' && row.items) {
410410
rows[idx] = internalAccessList.maskItems(row);
411411
}
@@ -424,7 +424,7 @@ const internalAccessList = {
424424
* @returns {Promise}
425425
*/
426426
getCount: (user_id, visibility) => {
427-
let query = accessListModel
427+
const query = accessListModel
428428
.query()
429429
.count('id as count')
430430
.where('is_deleted', 0);
@@ -445,7 +445,7 @@ const internalAccessList = {
445445
*/
446446
maskItems: (list) => {
447447
if (list && typeof list.items !== 'undefined') {
448-
list.items.map(function (val, idx) {
448+
list.items.map((val, idx) => {
449449
let repeat_for = 8;
450450
let first_char = '*';
451451

@@ -468,7 +468,7 @@ const internalAccessList = {
468468
* @returns {String}
469469
*/
470470
getFilename: (list) => {
471-
return '/data/access/' + list.id;
471+
return `/data/access/${list.id}`;
472472
},
473473

474474
/**
@@ -479,15 +479,15 @@ const internalAccessList = {
479479
* @returns {Promise}
480480
*/
481481
build: (list) => {
482-
logger.info('Building Access file #' + list.id + ' for: ' + list.name);
482+
logger.info(`Building Access file #${list.id} for: ${list.name}`);
483483

484484
return new Promise((resolve, reject) => {
485-
let htpasswd_file = internalAccessList.getFilename(list);
485+
const htpasswd_file = internalAccessList.getFilename(list);
486486

487487
// 1. remove any existing access file
488488
try {
489489
fs.unlinkSync(htpasswd_file);
490-
} catch (err) {
490+
} catch (_err) {
491491
// do nothing
492492
}
493493

@@ -504,14 +504,14 @@ const internalAccessList = {
504504
if (list.items.length) {
505505
return new Promise((resolve, reject) => {
506506
batchflow(list.items).sequential()
507-
.each((i, item, next) => {
507+
.each((_i, item, next) => {
508508
if (typeof item.password !== 'undefined' && item.password.length) {
509-
logger.info('Adding: ' + item.username);
509+
logger.info(`Adding: ${item.username}`);
510510

511511
utils.execFile('openssl', ['passwd', '-apr1', item.password])
512512
.then((res) => {
513513
try {
514-
fs.appendFileSync(htpasswd_file, item.username + ':' + res + '\n', {encoding: 'utf8'});
514+
fs.appendFileSync(htpasswd_file, `${item.username}:${res}\n`, {encoding: 'utf8'});
515515
} catch (err) {
516516
reject(err);
517517
}
@@ -528,7 +528,7 @@ const internalAccessList = {
528528
reject(err);
529529
})
530530
.end((results) => {
531-
logger.success('Built Access file #' + list.id + ' for: ' + list.name);
531+
logger.success(`Built Access file #${list.id} for: ${list.name}`);
532532
resolve(results);
533533
});
534534
});

0 commit comments

Comments
 (0)