Skip to content

Commit 4096518

Browse files
Marco129drew-gross
authored andcommitted
Mask sensitive information when logging (#1790)
1 parent b40e166 commit 4096518

File tree

2 files changed

+89
-2
lines changed

2 files changed

+89
-2
lines changed

spec/FileLoggerAdapter.spec.js

+55
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
'use strict';
2+
13
var FileLoggerAdapter = require('../src/Adapters/Logger/FileLoggerAdapter').FileLoggerAdapter;
24
var Parse = require('parse/node').Parse;
5+
var request = require('request');
36

47
describe('info logs', () => {
58

@@ -45,3 +48,55 @@ describe('error logs', () => {
4548
});
4649
});
4750
});
51+
52+
describe('verbose logs', () => {
53+
54+
it("mask sensitive information in _User class", (done) => {
55+
let customConfig = Object.assign({}, defaultConfiguration, {verbose: true});
56+
setServerConfiguration(customConfig);
57+
createTestUser().then(() => {
58+
let fileLoggerAdapter = new FileLoggerAdapter();
59+
return fileLoggerAdapter.query({
60+
from: new Date(Date.now() - 500),
61+
size: 100,
62+
level: 'verbose'
63+
});
64+
}).then((results) => {
65+
expect(results[1].message.includes('"password": "********"')).toEqual(true);
66+
var headers = {
67+
'X-Parse-Application-Id': 'test',
68+
'X-Parse-REST-API-Key': 'rest'
69+
};
70+
request.get({
71+
headers: headers,
72+
url: 'http://localhost:8378/1/login?username=test&password=moon-y'
73+
}, (error, response, body) => {
74+
let fileLoggerAdapter = new FileLoggerAdapter();
75+
return fileLoggerAdapter.query({
76+
from: new Date(Date.now() - 500),
77+
size: 100,
78+
level: 'verbose'
79+
}).then((results) => {
80+
expect(results[1].message.includes('password=********')).toEqual(true);
81+
done();
82+
});
83+
});
84+
});
85+
});
86+
87+
it("should not mask information in non _User class", (done) => {
88+
let obj = new Parse.Object('users');
89+
obj.set('password', 'pw');
90+
obj.save().then(() => {
91+
let fileLoggerAdapter = new FileLoggerAdapter();
92+
return fileLoggerAdapter.query({
93+
from: new Date(Date.now() - 500),
94+
size: 100,
95+
level: 'verbose'
96+
});
97+
}).then((results) => {
98+
expect(results[1].message.includes('"password": "pw"')).toEqual(true);
99+
done();
100+
});
101+
});
102+
});

src/PromiseRouter.js

+34-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// components that external developers may be modifying.
77

88
import express from 'express';
9+
import url from 'url';
910
import log from './logger';
1011

1112
export default class PromiseRouter {
@@ -154,8 +155,8 @@ export default class PromiseRouter {
154155
function makeExpressHandler(promiseHandler) {
155156
return function(req, res, next) {
156157
try {
157-
log.verbose(req.method, req.originalUrl, req.headers,
158-
JSON.stringify(req.body, null, 2));
158+
log.verbose(req.method, maskSensitiveUrl(req), req.headers,
159+
JSON.stringify(maskSensitiveBody(req), null, 2));
159160
promiseHandler(req).then((result) => {
160161
if (!result.response && !result.location && !result.text) {
161162
log.error('the handler did not include a "response" or a "location" field');
@@ -194,3 +195,34 @@ function makeExpressHandler(promiseHandler) {
194195
}
195196
}
196197
}
198+
199+
function maskSensitiveBody(req) {
200+
let maskBody = Object.assign({}, req.body);
201+
let shouldMaskBody = (req.method === 'POST' && req.originalUrl.endsWith('/users')
202+
&& !req.originalUrl.includes('classes')) ||
203+
(req.method === 'PUT' && /users\/\w+$/.test(req.originalUrl)
204+
&& !req.originalUrl.includes('classes')) ||
205+
(req.originalUrl.includes('classes/_User'));
206+
if (shouldMaskBody) {
207+
for (let key of Object.keys(maskBody)) {
208+
if (key == 'password') {
209+
maskBody[key] = '********';
210+
break;
211+
}
212+
}
213+
}
214+
return maskBody;
215+
}
216+
217+
function maskSensitiveUrl(req) {
218+
let maskUrl = req.originalUrl.toString();
219+
let shouldMaskUrl = req.method === 'GET' && req.originalUrl.includes('/login')
220+
&& !req.originalUrl.includes('classes');
221+
if (shouldMaskUrl) {
222+
let password = url.parse(req.originalUrl, true).query.password;
223+
if (password) {
224+
maskUrl = maskUrl.replace('password=' + password, 'password=********')
225+
}
226+
}
227+
return maskUrl;
228+
}

0 commit comments

Comments
 (0)