From 20b8c6817276b18cc1034c47b0e1fdd70ddadc76 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Thu, 9 Feb 2023 19:39:07 -0500 Subject: [PATCH 01/10] feat(replay): Upgrade to `rrweb@1.102.0` - feat: Add `maskAllText` option - feat: With maskAllText, mask the attributes: placeholder, title, `aria-label` - feat: fix masking on `textarea` --- packages/replay/package.json | 1 + yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/replay/package.json b/packages/replay/package.json index 058457ae576c..de3e25700d8e 100644 --- a/packages/replay/package.json +++ b/packages/replay/package.json @@ -53,6 +53,7 @@ "tslib": "^1.9.3" }, "dependencies": { + "@sentry-internal/rrweb": "1.102.0", "@sentry/core": "7.37.0", "@sentry/types": "7.37.0", "@sentry/utils": "7.37.0" diff --git a/yarn.lock b/yarn.lock index 8fb259ed02e0..1b9a0ca3018a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3158,17 +3158,17 @@ semver "7.3.2" semver-intersect "1.4.0" -"@sentry-internal/rrweb-snapshot@1.101.2": - version "1.101.2" - resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-snapshot/-/rrweb-snapshot-1.101.2.tgz#cf73629374812f110ab7271f9da65f1afc6c08c3" - integrity sha512-wbc/lQ4ta7zXZGFU3sFfTz8PVcfOTeI2H2l2bo4BehZiQEEDTrqhGSFe5Nzq6Noi38CZyPT0kweGI4fUk1u0KQ== +"@sentry-internal/rrweb-snapshot@1.102.0": + version "1.102.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-snapshot/-/rrweb-snapshot-1.102.0.tgz#d9a68fe89a51feda1fe1a5385ef3ae84c773dbac" + integrity sha512-DLAKilL1/xr3OlC9VYBF5p1YbmU4WgKv4j9NBsUw/dM8qLcLLxZaS6oBKunoSQrMvZn4BtvTn7REzBb8lUt9Vw== -"@sentry-internal/rrweb@1.101.2": - version "1.101.2" - resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb/-/rrweb-1.101.2.tgz#65e5d80745e1c01c2f66031fb807b36837283944" - integrity sha512-IaDgoo9kxnwC6xn25yLU0ymKLVBAWGEH90iMdweTC7Izhza6k4oTy01t4/wy7ORCnfCeHZYJ4gkNJJyi4J1XHQ== +"@sentry-internal/rrweb@1.102.0": + version "1.102.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb/-/rrweb-1.102.0.tgz#85bbd35594c4ef25427502be6e34c994b66559bc" + integrity sha512-GyU6UPN8RLlDQFyW0CRL30Gv+q02Qk01C83wSDuwnMRUeFufU5Ybj2zqlnh4HCali/JMaKmQlLT+C0EVPpwmwA== dependencies: - "@sentry-internal/rrweb-snapshot" "1.101.2" + "@sentry-internal/rrweb-snapshot" "1.102.0" "@types/css-font-loading-module" "0.0.7" "@xstate/fsm" "^1.4.0" base64-arraybuffer "^1.0.1" From ffa222a5cd0998f14763e53dccdc8a2f0a9b3b66 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Thu, 9 Feb 2023 19:43:46 -0500 Subject: [PATCH 02/10] remove old `maskAllText` logic --- packages/replay/src/constants.ts | 3 --- packages/replay/src/integration.ts | 13 +++---------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/packages/replay/src/constants.ts b/packages/replay/src/constants.ts index 434c64158cb4..87bf1823b056 100644 --- a/packages/replay/src/constants.ts +++ b/packages/replay/src/constants.ts @@ -20,9 +20,6 @@ export const VISIBILITY_CHANGE_TIMEOUT = SESSION_IDLE_DURATION; // The maximum length of a session export const MAX_SESSION_LIFE = 3_600_000; // 60 minutes -/** The select to use for the `maskAllText` option */ -export const MASK_ALL_TEXT_SELECTOR = 'body *:not(style), body *:not(script)'; - /** Default flush delays */ export const DEFAULT_FLUSH_MIN_DELAY = 5_000; export const DEFAULT_FLUSH_MAX_DELAY = 5_000; diff --git a/packages/replay/src/integration.ts b/packages/replay/src/integration.ts index d7c67b403f77..7f65b2e3d6a2 100644 --- a/packages/replay/src/integration.ts +++ b/packages/replay/src/integration.ts @@ -2,7 +2,7 @@ import { getCurrentHub } from '@sentry/core'; import type { BrowserClientReplayOptions, Integration } from '@sentry/types'; import { dropUndefinedKeys } from '@sentry/utils'; -import { DEFAULT_FLUSH_MAX_DELAY, DEFAULT_FLUSH_MIN_DELAY, MASK_ALL_TEXT_SELECTOR } from './constants'; +import { DEFAULT_FLUSH_MAX_DELAY, DEFAULT_FLUSH_MIN_DELAY } from './constants'; import { ReplayContainer } from './replay'; import type { RecordingOptions, ReplayConfiguration, ReplayPluginOptions } from './types'; import { getPrivacyOptions } from './util/getPrivacyOptions'; @@ -53,7 +53,7 @@ export class Replay implements Integration { _experiments = {}, sessionSampleRate, errorSampleRate, - maskAllText, + maskAllText = true, maskAllInputs = true, blockAllMedia = true, @@ -113,7 +113,7 @@ export class Replay implements Integration { sessionSampleRate, errorSampleRate, useCompression, - maskAllText: typeof maskAllText === 'boolean' ? maskAllText : !maskTextSelector, + maskAllText, blockAllMedia, _experiments, }; @@ -142,13 +142,6 @@ Sentry.init({ replaysOnErrorSampleRate: ${errorSampleRate} })`, this._initialOptions.errorSampleRate = errorSampleRate; } - if (this._initialOptions.maskAllText) { - // `maskAllText` is a more user friendly option to configure - // `maskTextSelector`. This means that all nodes will have their text - // content masked. - this._recordingOptions.maskTextSelector = MASK_ALL_TEXT_SELECTOR; - } - if (this._initialOptions.blockAllMedia) { // `blockAllMedia` is a more user friendly option to configure blocking // embedded media elements From c564c68aa9f13647cd43e860159f63903d36dfac Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Thu, 9 Feb 2023 19:53:43 -0500 Subject: [PATCH 03/10] fix interface + tests --- packages/replay/src/integration.ts | 2 +- packages/replay/src/types.ts | 7 +------ packages/replay/src/types/rrweb.ts | 1 + .../integration/integrationSettings.test.ts | 18 ++++++------------ packages/replay/test/integration/rrweb.test.ts | 3 ++- 5 files changed, 11 insertions(+), 20 deletions(-) diff --git a/packages/replay/src/integration.ts b/packages/replay/src/integration.ts index 7f65b2e3d6a2..14dc260099f9 100644 --- a/packages/replay/src/integration.ts +++ b/packages/replay/src/integration.ts @@ -79,6 +79,7 @@ export class Replay implements Integration { }: ReplayConfiguration = {}) { this._recordingOptions = { maskAllInputs, + maskAllText, maskInputOptions: { ...(maskInputOptions || {}), password: true }, maskTextFn: maskFn, maskInputFn: maskFn, @@ -113,7 +114,6 @@ export class Replay implements Integration { sessionSampleRate, errorSampleRate, useCompression, - maskAllText, blockAllMedia, _experiments, }; diff --git a/packages/replay/src/types.ts b/packages/replay/src/types.ts index 136ce1e526a3..95703223000c 100644 --- a/packages/replay/src/types.ts +++ b/packages/replay/src/types.ts @@ -90,11 +90,6 @@ export interface ReplayPluginOptions extends SessionOptions { */ useCompression: boolean; - /** - * Mask all text in recordings. All text will be replaced with asterisks by default. - */ - maskAllText: boolean; - /** * Block all media (e.g. images, svg, video) in recordings. */ @@ -180,7 +175,7 @@ export interface ReplayConfiguration extends ReplayIntegrationPrivacyOptions, OptionalReplayPluginOptions, DeprecatedPrivacyOptions, - Pick {} + Pick {} interface CommonEventContext { /** diff --git a/packages/replay/src/types/rrweb.ts b/packages/replay/src/types/rrweb.ts index 3628d45ef9ab..7a794face4cb 100644 --- a/packages/replay/src/types/rrweb.ts +++ b/packages/replay/src/types/rrweb.ts @@ -30,6 +30,7 @@ export type eventWithTime = { * Record union type. */ export type recordOptions = { + maskAllText?: boolean; maskAllInputs?: boolean; blockClass?: blockClass; ignoreClass?: string; diff --git a/packages/replay/test/integration/integrationSettings.test.ts b/packages/replay/test/integration/integrationSettings.test.ts index dd23b1a4cfdb..35f9245a9880 100644 --- a/packages/replay/test/integration/integrationSettings.test.ts +++ b/packages/replay/test/integration/integrationSettings.test.ts @@ -1,4 +1,3 @@ -import { MASK_ALL_TEXT_SELECTOR } from '../../src/constants'; import { mockSdk } from '../index'; describe('Integration | integrationSettings', () => { @@ -191,33 +190,28 @@ describe('Integration | integrationSettings', () => { it('works with default value', async () => { const { replay } = await mockSdk({ replayOptions: {} }); - // Default is true - expect(replay['_recordingOptions'].maskTextSelector).toBe(MASK_ALL_TEXT_SELECTOR); + expect(replay['_recordingOptions'].maskAllText).toBe(true); }); it('works with true', async () => { const { replay } = await mockSdk({ replayOptions: { maskAllText: true } }); - expect(replay['_recordingOptions'].maskTextSelector).toBe(MASK_ALL_TEXT_SELECTOR); + expect(replay['_recordingOptions'].maskAllText).toBe(true); }); it('works with false', async () => { const { replay } = await mockSdk({ replayOptions: { maskAllText: false } }); - expect(replay['_recordingOptions'].maskTextSelector).toBe('.sentry-mask,[data-sentry-mask]'); + expect(replay['_recordingOptions'].maskAllText).toBe(false); }); + }); - it('maskTextSelector takes precedence over maskAllText when not specifiying maskAllText:true', async () => { + describe('maskTextSelector', () => { + it('can have custom mask selector', async () => { const { replay } = await mockSdk({ replayOptions: { maskTextSelector: '[custom]' } }); expect(replay['_recordingOptions'].maskTextSelector).toBe('[custom],.sentry-mask,[data-sentry-mask]'); }); - - it('maskAllText takes precedence over maskTextSelector when specifiying maskAllText:true', async () => { - const { replay } = await mockSdk({ replayOptions: { maskAllText: true, maskTextSelector: '[custom]' } }); - - expect(replay['_recordingOptions'].maskTextSelector).toBe(MASK_ALL_TEXT_SELECTOR); - }); }); describe('_experiments', () => { diff --git a/packages/replay/test/integration/rrweb.test.ts b/packages/replay/test/integration/rrweb.test.ts index 00e1fb09af97..e3b00d55271a 100644 --- a/packages/replay/test/integration/rrweb.test.ts +++ b/packages/replay/test/integration/rrweb.test.ts @@ -24,13 +24,14 @@ describe('Integration | rrweb', () => { "inlineImages": false, "inlineStylesheet": true, "maskAllInputs": true, + "maskAllText": true, "maskInputFn": undefined, "maskInputOptions": Object { "password": true, }, "maskInputSelector": ".sentry-mask,[data-sentry-mask]", "maskTextFn": undefined, - "maskTextSelector": "body *:not(style), body *:not(script)", + "maskTextSelector": ".sentry-mask,[data-sentry-mask]", "slimDOMOptions": "all", "unblockSelector": ".sentry-unblock,[data-sentry-unblock]", "unmaskInputSelector": ".sentry-unmask,[data-sentry-unmask]", From 312cbcf0c7ad4579b6a1f85fbe1d03079cdc5eae Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Thu, 9 Feb 2023 19:58:27 -0500 Subject: [PATCH 04/10] dev deps --- packages/replay/package.json | 3 +-- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/replay/package.json b/packages/replay/package.json index de3e25700d8e..aa06a0ab48ae 100644 --- a/packages/replay/package.json +++ b/packages/replay/package.json @@ -46,14 +46,13 @@ "homepage": "https://docs.sentry.io/platforms/javascript/session-replay/", "devDependencies": { "@babel/core": "^7.17.5", - "@sentry-internal/rrweb": "1.101.2", + "@sentry-internal/rrweb": "^1.102.0", "@types/pako": "^2.0.0", "jsdom-worker": "^0.2.1", "pako": "^2.0.4", "tslib": "^1.9.3" }, "dependencies": { - "@sentry-internal/rrweb": "1.102.0", "@sentry/core": "7.37.0", "@sentry/types": "7.37.0", "@sentry/utils": "7.37.0" diff --git a/yarn.lock b/yarn.lock index 1b9a0ca3018a..790dad9cdf32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3163,7 +3163,7 @@ resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-snapshot/-/rrweb-snapshot-1.102.0.tgz#d9a68fe89a51feda1fe1a5385ef3ae84c773dbac" integrity sha512-DLAKilL1/xr3OlC9VYBF5p1YbmU4WgKv4j9NBsUw/dM8qLcLLxZaS6oBKunoSQrMvZn4BtvTn7REzBb8lUt9Vw== -"@sentry-internal/rrweb@1.102.0": +"@sentry-internal/rrweb@^1.102.0": version "1.102.0" resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb/-/rrweb-1.102.0.tgz#85bbd35594c4ef25427502be6e34c994b66559bc" integrity sha512-GyU6UPN8RLlDQFyW0CRL30Gv+q02Qk01C83wSDuwnMRUeFufU5Ybj2zqlnh4HCali/JMaKmQlLT+C0EVPpwmwA== From 0454d8f0973bc0b33304a2407bd14d257f2be90e Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Thu, 9 Feb 2023 21:18:42 -0500 Subject: [PATCH 05/10] lint --- packages/replay/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/replay/src/types.ts b/packages/replay/src/types.ts index 95703223000c..27c878a3edba 100644 --- a/packages/replay/src/types.ts +++ b/packages/replay/src/types.ts @@ -175,7 +175,7 @@ export interface ReplayConfiguration extends ReplayIntegrationPrivacyOptions, OptionalReplayPluginOptions, DeprecatedPrivacyOptions, - Pick {} + Pick {} interface CommonEventContext { /** From a440a6c0ec4aa248e5e81125934d8c14b4038782 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Fri, 10 Feb 2023 10:38:35 -0500 Subject: [PATCH 06/10] pin version --- packages/replay/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/replay/package.json b/packages/replay/package.json index aa06a0ab48ae..0f02b3181997 100644 --- a/packages/replay/package.json +++ b/packages/replay/package.json @@ -46,7 +46,7 @@ "homepage": "https://docs.sentry.io/platforms/javascript/session-replay/", "devDependencies": { "@babel/core": "^7.17.5", - "@sentry-internal/rrweb": "^1.102.0", + "@sentry-internal/rrweb": "1.102.0", "@types/pako": "^2.0.0", "jsdom-worker": "^0.2.1", "pako": "^2.0.4", From dbecb681b5768eab05862e7a3da30ab7356c3c6d Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Fri, 10 Feb 2023 10:39:52 -0500 Subject: [PATCH 07/10] pin version --- yarn.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 790dad9cdf32..1b9a0ca3018a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3163,7 +3163,7 @@ resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-snapshot/-/rrweb-snapshot-1.102.0.tgz#d9a68fe89a51feda1fe1a5385ef3ae84c773dbac" integrity sha512-DLAKilL1/xr3OlC9VYBF5p1YbmU4WgKv4j9NBsUw/dM8qLcLLxZaS6oBKunoSQrMvZn4BtvTn7REzBb8lUt9Vw== -"@sentry-internal/rrweb@^1.102.0": +"@sentry-internal/rrweb@1.102.0": version "1.102.0" resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb/-/rrweb-1.102.0.tgz#85bbd35594c4ef25427502be6e34c994b66559bc" integrity sha512-GyU6UPN8RLlDQFyW0CRL30Gv+q02Qk01C83wSDuwnMRUeFufU5Ybj2zqlnh4HCali/JMaKmQlLT+C0EVPpwmwA== From 4a27f20045130cb9606e4cdc7b398cc5a750b80b Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Fri, 10 Feb 2023 10:54:54 -0500 Subject: [PATCH 08/10] move maskAllText --- packages/replay/test/utils/setupReplayContainer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/replay/test/utils/setupReplayContainer.ts b/packages/replay/test/utils/setupReplayContainer.ts index fd6a5baa40e0..15eaa47d5736 100644 --- a/packages/replay/test/utils/setupReplayContainer.ts +++ b/packages/replay/test/utils/setupReplayContainer.ts @@ -16,12 +16,12 @@ export function setupReplayContainer({ sessionSampleRate: 0, errorSampleRate: 1, useCompression: false, - maskAllText: true, blockAllMedia: true, _experiments: {}, ...options, }, recordingOptions: { + maskAllText: true, ...recordingOptions, }, }); From de0d4179346ec77d6ce168ae53246e566e07f1a0 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Fri, 10 Feb 2023 11:12:51 -0500 Subject: [PATCH 09/10] fix tests after removing snapshots --- packages/integration-tests/suites/replay/privacy/test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/integration-tests/suites/replay/privacy/test.ts b/packages/integration-tests/suites/replay/privacy/test.ts index 3ad8ee5684fb..89916b0ea01e 100644 --- a/packages/integration-tests/suites/replay/privacy/test.ts +++ b/packages/integration-tests/suites/replay/privacy/test.ts @@ -80,7 +80,7 @@ sentryTest('should have the correct default privacy settings', async ({ getLocal type: 2, tagName: 'button', attributes: { - 'aria-label': 'Click me', + 'aria-label': '***** **', onclick: "console.log('Test log')", }, childNodes: [ @@ -124,7 +124,7 @@ sentryTest('should have the correct default privacy settings', async ({ getLocal childNodes: [ { type: 3, - textContent: 'This should be unmasked due to data attribute', + textContent: '**** ****** ** ******** *** ** **** *********', id: 16, }, ], @@ -139,7 +139,7 @@ sentryTest('should have the correct default privacy settings', async ({ getLocal type: 2, tagName: 'input', attributes: { - placeholder: 'Placeholder should be masked', + placeholder: '*********** ****** ** ******', }, childNodes: [], id: 18, @@ -153,7 +153,7 @@ sentryTest('should have the correct default privacy settings', async ({ getLocal type: 2, tagName: 'div', attributes: { - title: 'Title should be masked', + title: '***** ****** ** ******', }, childNodes: [ { From b5ced92479b408c25f2750147dff2739734ed46e Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Fri, 10 Feb 2023 11:59:08 -0500 Subject: [PATCH 10/10] unmasked, need snapshots --- packages/integration-tests/suites/replay/privacy/test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integration-tests/suites/replay/privacy/test.ts b/packages/integration-tests/suites/replay/privacy/test.ts index 89916b0ea01e..aed810f7c002 100644 --- a/packages/integration-tests/suites/replay/privacy/test.ts +++ b/packages/integration-tests/suites/replay/privacy/test.ts @@ -124,7 +124,7 @@ sentryTest('should have the correct default privacy settings', async ({ getLocal childNodes: [ { type: 3, - textContent: '**** ****** ** ******** *** ** **** *********', + textContent: 'This should be unmasked due to data attribute', id: 16, }, ],