Skip to content

Commit ad70745

Browse files
authored
Obfuscate password name value pairs in log strings (#2755)
* Unit test to catch password in logs. * Add clean to logger controller to "look for" password strings in log messages.
1 parent 5feceaa commit ad70745

File tree

4 files changed

+33
-7
lines changed

4 files changed

+33
-7
lines changed

spec/CloudCodeLogger.spec.js

+18
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,24 @@ describe("Cloud Code Logger", () => {
5555
});
5656
});
5757

58+
it('trigger should obfuscate password', done => {
59+
const logController = new LoggerController(new WinstonLoggerAdapter());
60+
61+
Parse.Cloud.beforeSave(Parse.User, (req, res) => {
62+
res.success(req.object);
63+
});
64+
65+
Parse.User.signUp('tester123', 'abc')
66+
.then(() => logController.getLogs({ from: Date.now() - 500, size: 1000 }))
67+
.then((res) => {
68+
const entry = res[0];
69+
expect(entry.message).not.toMatch(/password":"abc/);
70+
expect(entry.message).toMatch(/\*\*\*\*\*\*\*\*/);
71+
done();
72+
})
73+
.then(null, e => done.fail(e));
74+
});
75+
5876
it("should expose log to trigger", (done) => {
5977
var logController = new LoggerController(new WinstonLoggerAdapter());
6078

src/Controllers/LoggerController.js

+8
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ export class LoggerController extends AdaptableController {
6161
return null;
6262
}
6363

64+
cleanAndTruncateLogMessage(string) {
65+
return this.truncateLogMessage(this.cleanLogMessage(string));
66+
}
67+
68+
cleanLogMessage(string) {
69+
return string.replace(/password":"[^"]*"/g, 'password":"********"');
70+
}
71+
6472
truncateLogMessage(string) {
6573
if (string && string.length > LOG_STRING_TRUNCATE_LENGTH) {
6674
const truncated = string.substring(0, LOG_STRING_TRUNCATE_LENGTH) + truncationMarker;

src/Routers/FunctionsRouter.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export class FunctionsRouter extends PromiseRouter {
103103
const applicationId = req.config.applicationId;
104104
const theFunction = triggers.getFunction(functionName, applicationId);
105105
const theValidator = triggers.getValidator(req.params.functionName, applicationId);
106-
if (theFunction) {
106+
if (theFunction) {
107107
let params = Object.assign({}, req.body, req.query);
108108
params = parseParams(params);
109109
var request = {
@@ -125,10 +125,10 @@ export class FunctionsRouter extends PromiseRouter {
125125

126126
return new Promise(function (resolve, reject) {
127127
const userString = (req.auth && req.auth.user) ? req.auth.user.id : undefined;
128-
const cleanInput = logger.truncateLogMessage(JSON.stringify(params));
128+
const cleanInput = logger.cleanAndTruncateLogMessage(JSON.stringify(params));
129129
var response = FunctionsRouter.createResponseObject((result) => {
130130
try {
131-
const cleanResult = logger.truncateLogMessage(JSON.stringify(result.response.result));
131+
const cleanResult = logger.cleanAndTruncateLogMessage(JSON.stringify(result.response.result));
132132
logger.info(`Ran cloud function ${functionName} for user ${userString} `
133133
+ `with:\n Input: ${cleanInput }\n Result: ${cleanResult }`, {
134134
functionName,

src/triggers.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ function userIdForLog(auth) {
212212
}
213213

214214
function logTriggerAfterHook(triggerType, className, input, auth) {
215-
const cleanInput = logger.truncateLogMessage(JSON.stringify(input));
215+
const cleanInput = logger.cleanAndTruncateLogMessage(JSON.stringify(input));
216216
logger.info(`${triggerType} triggered for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}`, {
217217
className,
218218
triggerType,
@@ -221,8 +221,8 @@ function logTriggerAfterHook(triggerType, className, input, auth) {
221221
}
222222

223223
function logTriggerSuccessBeforeHook(triggerType, className, input, result, auth) {
224-
const cleanInput = logger.truncateLogMessage(JSON.stringify(input));
225-
const cleanResult = logger.truncateLogMessage(JSON.stringify(result));
224+
const cleanInput = logger.cleanAndTruncateLogMessage(JSON.stringify(input));
225+
const cleanResult = logger.cleanAndTruncateLogMessage(JSON.stringify(result));
226226
logger.info(`${triggerType} triggered for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}\n Result: ${cleanResult}`, {
227227
className,
228228
triggerType,
@@ -231,7 +231,7 @@ function logTriggerSuccessBeforeHook(triggerType, className, input, result, auth
231231
}
232232

233233
function logTriggerErrorBeforeHook(triggerType, className, input, auth, error) {
234-
const cleanInput = logger.truncateLogMessage(JSON.stringify(input));
234+
const cleanInput = logger.cleanAndTruncateLogMessage(JSON.stringify(input));
235235
logger.error(`${triggerType} failed for ${className} for user ${userIdForLog(auth)}:\n Input: ${cleanInput}\n Error: ${JSON.stringify(error)}`, {
236236
className,
237237
triggerType,

0 commit comments

Comments
 (0)