From be3e4d86c2be10a51559dc53305df6cfe5920b70 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Tue, 6 Mar 2018 12:04:37 -0500 Subject: [PATCH] Add `Errors.toLogFormat` Allows errors to be formatted and sanitized for logging. Removes sensitive paths such as the app root directory. Ideally, this module would be called singular `Error` but that is already a global name. Using `Errors` plural is similar to Java convention for utilities such as `Arrays`, `Collections`, `Files`, etc. See: https://stackoverflow.com/a/11673838 --- js/modules/types/errors.js | 17 ++++++++++++++ test/modules/types/errors_test.js | 39 +++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 js/modules/types/errors.js create mode 100644 test/modules/types/errors_test.js diff --git a/js/modules/types/errors.js b/js/modules/types/errors.js new file mode 100644 index 00000000000..7754bb15c4e --- /dev/null +++ b/js/modules/types/errors.js @@ -0,0 +1,17 @@ +/* eslint-env node */ + +const Path = require('path'); + +const toError = require('ensure-error'); + + +const APP_ROOT_PATH = Path.join(__dirname, '..', '..', '..'); +const APP_ROOT_PATH_PATTERN = new RegExp(APP_ROOT_PATH, 'g'); + +// toLogFormat :: Error -> String +exports.toLogFormat = (error) => { + const normalizedError = toError(error); + const stackWithoutPrivatePaths = + normalizedError.stack.replace(APP_ROOT_PATH_PATTERN, ''); + return stackWithoutPrivatePaths; +}; diff --git a/test/modules/types/errors_test.js b/test/modules/types/errors_test.js new file mode 100644 index 00000000000..74a9f4e5142 --- /dev/null +++ b/test/modules/types/errors_test.js @@ -0,0 +1,39 @@ +const Path = require('path'); + +const { assert } = require('chai'); + +const Errors = require('../../../js/modules/types/errors'); + + +const APP_ROOT_PATH = Path.join(__dirname, '..', '..', '..'); + +describe('Errors', () => { + describe('toLogFormat', () => { + it('should redact sensitive paths in stack trace', () => { + try { + throw new Error('boom'); + } catch (error) { + assert.include( + error.stack, + APP_ROOT_PATH, + 'Unformatted stack has sensitive paths' + ); + + const formattedStack = Errors.toLogFormat(error); + assert.notInclude( + formattedStack, + APP_ROOT_PATH, + 'Formatted stack does not have sensitive paths' + ); + assert.include( + formattedStack, + '', + 'Formatted stack has redactions' + ); + return; + } + // eslint-disable-next-line no-unreachable + assert.fail('Expected error to be thrown.'); + }); + }); +});