Skip to content

Commit 2e07a90

Browse files
fix(users): hide sensitive data from errors 🐛
1 parent cdc06e4 commit 2e07a90

File tree

6 files changed

+46
-28
lines changed

6 files changed

+46
-28
lines changed

config/defaults/development.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,21 @@ module.exports = {
7676
host: 'localhost',
7777
port: '4200',
7878
},
79-
illegalUsernames: ['waos', 'weareopensource', 'administrator', 'password', 'admin', 'user', 'unknown', 'anonymous', 'null', 'undefined', 'api'],
80-
roles: ['user', 'admin'],
79+
// Data filter whitelist & Blacklist
80+
blacklists: {
81+
users: {
82+
usernames: ['waos', 'weareopensource', 'administrator', 'password', 'admin', 'user', 'unknown', 'anonymous', 'null', 'undefined', 'api'],
83+
},
84+
},
85+
whitelists: {
86+
users: {
87+
default: ['_id', 'id', 'firstName', 'lastName', 'displayName', 'username', 'email', 'roles', 'profileImageURL', 'updated', 'created', 'resetPasswordToken', 'resetPasswordExpires'],
88+
update: ['firstName', 'lastName', 'username', 'email', 'profileImageURL'],
89+
updateAdmin: ['firstName', 'lastName', 'username', 'email', 'profileImageURL', 'roles'],
90+
recover: ['password', 'resetPasswordToken', 'resetPasswordExpires'],
91+
roles: ['user', 'admin'],
92+
},
93+
},
8194
uploads: {
8295
profile: {
8396
avatar: {

lib/middlewares/model.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ module.exports.isValid = schema => (req, res, next) => {
4343
// Validate req.body using the schema and validation options
4444
const result = getResultFromJoi(req.body, schema, options);
4545
// if error
46-
if (result && result.error) return responses.error(res, 422, 'schema validation error')(result.error);
46+
if (result && result.error) {
47+
if (result.error.original && (result.error.original.password || result.error.original.firstname)) result.error.original = _.pick(result.error.original, config.whitelists.users.default);
48+
return responses.error(res, 422, 'schema validation error')(result.error);
49+
}
4750
// else return req.body with the data after Joi validation
4851
req.body = result;
4952
return next();

modules/users/models/user.schema.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ const UserSchema = Joi.object().keys({
1919
email: Joi.string().email({ minDomainAtoms: 2 }),
2020
username: Joi.string().lowercase().trim()
2121
.regex(/^(?=[\w.-]+$)(?!.*[._-]{2})(?!\.)(?!.*\.$).{3,34}$/)
22-
.invalid(config.illegalUsernames),
22+
.invalid(config.blacklists.users.usernames),
2323
profileImageURL: Joi.string(),
24-
roles: Joi.array().items(Joi.string().valid(config.roles)).min(1).default(['user']),
24+
roles: Joi.array().items(Joi.string().valid(config.whitelists.users.roles)).min(1).default(['user']),
2525
/* Extra */
2626
updated: Joi.date(),
2727
created: Joi.date().default(Date.now, 'current date'),

modules/users/services/user.service.js

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,6 @@ const imageFileFilter = require(path.resolve('./lib/services/multer')).imageFile
1515
const UserRepository = require('../repositories/user.repository');
1616

1717
const saltRounds = 10;
18-
// update whitelist
19-
const whitelistUpdate = ['firstName', 'lastName', 'username', 'email', 'profileImageURL'];
20-
const whitelistUpdateAdmin = whitelistUpdate.concat(['roles']);
21-
const whitelistRecover = ['password', 'resetPasswordToken', 'resetPasswordExpires'];
22-
// Data filter whitelist
23-
const whitelist = ['_id',
24-
'id',
25-
'firstName',
26-
'lastName',
27-
'displayName',
28-
'username',
29-
'email',
30-
'roles',
31-
'profileImageURL',
32-
'updated',
33-
'created',
34-
'resetPasswordToken',
35-
'resetPasswordExpires'];
3618

3719
/**
3820
* @desc Local function to removeSensitive data from user
@@ -41,7 +23,7 @@ const whitelist = ['_id',
4123
*/
4224
const removeSensitive = (user) => {
4325
if (!user || typeof user !== 'object') return null;
44-
return _.assignIn(user, _.pick(user, whitelist));
26+
return _.assignIn(user, _.pick(user, config.whitelists.users.default));
4527
};
4628

4729

@@ -98,9 +80,9 @@ exports.create = async (user) => {
9880
* @return {Promise} user -
9981
*/
10082
exports.update = async (user, body, option) => {
101-
if (!option) user = _.assignIn(user, _.pick(body, whitelistUpdate));
102-
else if (option === 'admin') user = _.assignIn(user, _.pick(body, whitelistUpdateAdmin));
103-
else if (option === 'recover') user = _.assignIn(user, _.pick(body, whitelistRecover));
83+
if (!option) user = _.assignIn(user, _.pick(body, config.whitelists.users.update));
84+
else if (option === 'admin') user = _.assignIn(user, _.pick(body, config.whitelists.users.updateAdmin));
85+
else if (option === 'recover') user = _.assignIn(user, _.pick(body, config.whitelists.users.recover));
10486

10587
user.updated = Date.now();
10688
user.displayName = `${user.firstName} ${user.lastName}`;

modules/users/tests/user.crud.tests.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,26 @@ describe('User CRUD Unit Tests :', () => {
104104
}
105105
});
106106

107+
test('if should not be able to register, should not return sensible data', async () => {
108+
// Init user edited
109+
_userEdited.username = 'register_new_user';
110+
_userEdited.email = 'register_new_user_@test.com';
111+
_userEdited.password = 'azerty';
112+
113+
try {
114+
const result = await agent.post('/api/auth/signup')
115+
.send(_userEdited)
116+
.expect(422);
117+
expect(result.body.type).toBe('error');
118+
expect(result.body.message).toBe('schema validation error');
119+
expect(result.body.error.details[0].message).toBe('password Password strength score 0 does not suffice the minimum of 3');
120+
expect(result.body.error.original.password).toBeUndefined();
121+
} catch (err) {
122+
console.log(err);
123+
expect(err).toBeFalsy();
124+
}
125+
});
126+
107127
test('should be able to register a new user ', async () => {
108128
// Init user edited
109129
_userEdited.username = 'register_new_user';

modules/users/tests/user.schema.tests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ describe('User Schema Unit Tests:', () => {
419419
});
420420

421421
test('should be able to show an error when try to valid with not allowed username', (done) => {
422-
user.username = config.illegalUsernames[Math.floor(Math.random() * config.illegalUsernames.length)];
422+
user.username = config.blacklists.users.usernames[Math.floor(Math.random() * config.blacklists.users.usernames.length)];
423423

424424
const result = Joi.validate(user, schema.User, options);
425425
expect(typeof result).toBe('object');

0 commit comments

Comments
 (0)