diff --git a/app/assets/javascripts/services/errorReporting.ts b/app/assets/javascripts/services/errorReporting.ts index 83ffd015bd4..7aeb87810ab 100644 --- a/app/assets/javascripts/services/errorReporting.ts +++ b/app/assets/javascripts/services/errorReporting.ts @@ -5,6 +5,16 @@ import Bugsnag from '@bugsnag/js'; declare const __VERSION__: string; +function redactFilePath(line: string): string { + const fileName = line.match(/\w+\.(html|js)?.*/)?.[0]; + const redacted = ''; + if (fileName) { + return redacted + '/' + fileName; + } else { + return redacted; + } +} + export function startErrorReporting() { if (storage.get(StorageKey.DisableErrorReporting)) { SNLog.onError = console.error; @@ -17,14 +27,51 @@ export function startErrorReporting() { appVersion: __VERSION__, collectUserIp: false, autoTrackSessions: false, - releaseStage: isDev ? 'development' : undefined + releaseStage: isDev ? 'development' : undefined, + onError(event) { + /** + * Redact any data that could be used to identify user, + * such as file paths. + */ + if (isDesktopApplication()) { + if (event.context) { + event.context = `Desktop/${redactFilePath(event.context)}`; + } + } + + if (event.request.url?.includes('file:')) { + event.request.url = redactFilePath(event.request.url); + } + + const originalStack = event.originalError.stack; + if ( + typeof originalStack === 'string' && + originalStack.includes('file:') + ) { + event.originalError.stack = originalStack + .split('\n') + .map((line) => + line.includes('file:') ? redactFilePath(line) : line + ) + .join('\n'); + } + + for (const error of event.errors) { + for (const stackFrame of error.stacktrace) { + if (stackFrame.file.includes('file:')) { + stackFrame.file = redactFilePath(stackFrame.file); + } + } + } + }, }); + if (isDev) { SNLog.onError = console.error; } else { SNLog.onError = (error) => { Bugsnag.notify(error); - } + }; } } catch (error) { console.error('Failed to start Bugsnag.', error);