diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6e96ee5251a6..451b3c828e26 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,7 +4,7 @@
- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
-## 7.31.1
+## 7.37.1
- fix(browser): Support `async` in stack frame urls (#7131)
- fix(nextjs): Make api route identifier stricter (#7126)
diff --git a/packages/integration-tests/suites/replay/privacy/init.js b/packages/integration-tests/suites/replay/privacy/init.js
new file mode 100644
index 000000000000..ccb9689a14d6
--- /dev/null
+++ b/packages/integration-tests/suites/replay/privacy/init.js
@@ -0,0 +1,18 @@
+import * as Sentry from '@sentry/browser';
+import { Replay } from '@sentry/replay';
+
+window.Sentry = Sentry;
+window.Replay = new Replay({
+ flushMinDelay: 200,
+ flushMaxDelay: 200,
+ useCompression: false,
+});
+
+Sentry.init({
+ dsn: 'https://public@dsn.ingest.sentry.io/1337',
+ sampleRate: 0,
+ replaysSessionSampleRate: 1.0,
+ replaysOnErrorSampleRate: 0.0,
+
+ integrations: [window.Replay],
+});
diff --git a/packages/integration-tests/suites/replay/privacy/template.html b/packages/integration-tests/suites/replay/privacy/template.html
new file mode 100644
index 000000000000..aa916d3f116e
--- /dev/null
+++ b/packages/integration-tests/suites/replay/privacy/template.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ This should be masked by default
+ This should be unmasked due to data attribute
+
+ Title should be masked
+
+
+
+
+
+
diff --git a/packages/integration-tests/suites/replay/privacy/test.ts b/packages/integration-tests/suites/replay/privacy/test.ts
new file mode 100644
index 000000000000..3ad8ee5684fb
--- /dev/null
+++ b/packages/integration-tests/suites/replay/privacy/test.ts
@@ -0,0 +1,268 @@
+import { expect } from '@playwright/test';
+import { EventType } from '@sentry-internal/rrweb';
+import type { RecordingEvent } from '@sentry/replay/build/npm/types/types';
+
+import { sentryTest } from '../../../utils/fixtures';
+import { envelopeRequestParser } from '../../../utils/helpers';
+import { waitForReplayRequest } from '../../../utils/replayHelpers';
+
+sentryTest('should have the correct default privacy settings', async ({ getLocalTestPath, page }) => {
+ // Replay bundles are es6 only
+ if (process.env.PW_BUNDLE && process.env.PW_BUNDLE.startsWith('bundle_es5')) {
+ sentryTest.skip();
+ }
+
+ const reqPromise0 = waitForReplayRequest(page, 0);
+
+ await page.route('https://dsn.ingest.sentry.io/**/*', route => {
+ return route.fulfill({
+ status: 200,
+ contentType: 'application/json',
+ body: JSON.stringify({ id: 'test-id' }),
+ });
+ });
+
+ const url = await getLocalTestPath({ testDir: __dirname });
+
+ await page.goto(url);
+ const replayPayload = envelopeRequestParser(await reqPromise0, 5);
+ const checkoutEvent = replayPayload.find(({ type }) => type === EventType.FullSnapshot);
+
+ expect(checkoutEvent?.data).toEqual({
+ node: {
+ type: 0,
+ childNodes: [
+ {
+ type: 1,
+ name: 'html',
+ publicId: '',
+ systemId: '',
+ id: 2,
+ },
+ {
+ type: 2,
+ tagName: 'html',
+ attributes: {},
+ childNodes: [
+ {
+ type: 2,
+ tagName: 'head',
+ attributes: {},
+ childNodes: [
+ {
+ type: 2,
+ tagName: 'meta',
+ attributes: {
+ charset: 'utf-8',
+ },
+ childNodes: [],
+ id: 5,
+ },
+ ],
+ id: 4,
+ },
+ {
+ type: 3,
+ textContent: '\n ',
+ id: 6,
+ },
+ {
+ type: 2,
+ tagName: 'body',
+ attributes: {},
+ childNodes: [
+ {
+ type: 3,
+ textContent: '\n ',
+ id: 8,
+ },
+ {
+ type: 2,
+ tagName: 'button',
+ attributes: {
+ 'aria-label': 'Click me',
+ onclick: "console.log('Test log')",
+ },
+ childNodes: [
+ {
+ type: 3,
+ textContent: '***** **',
+ id: 10,
+ },
+ ],
+ id: 9,
+ },
+ {
+ type: 3,
+ textContent: '\n ',
+ id: 11,
+ },
+ {
+ type: 2,
+ tagName: 'div',
+ attributes: {},
+ childNodes: [
+ {
+ type: 3,
+ textContent: '**** ****** ** ****** ** *******',
+ id: 13,
+ },
+ ],
+ id: 12,
+ },
+ {
+ type: 3,
+ textContent: '\n ',
+ id: 14,
+ },
+ {
+ type: 2,
+ tagName: 'div',
+ attributes: {
+ 'data-sentry-unmask': '',
+ },
+ childNodes: [
+ {
+ type: 3,
+ textContent: 'This should be unmasked due to data attribute',
+ id: 16,
+ },
+ ],
+ id: 15,
+ },
+ {
+ type: 3,
+ textContent: '\n ',
+ id: 17,
+ },
+ {
+ type: 2,
+ tagName: 'input',
+ attributes: {
+ placeholder: 'Placeholder should be masked',
+ },
+ childNodes: [],
+ id: 18,
+ },
+ {
+ type: 3,
+ textContent: '\n ',
+ id: 19,
+ },
+ {
+ type: 2,
+ tagName: 'div',
+ attributes: {
+ title: 'Title should be masked',
+ },
+ childNodes: [
+ {
+ type: 3,
+ textContent: '***** ****** ** ******',
+ id: 21,
+ },
+ ],
+ id: 20,
+ },
+ {
+ type: 3,
+ textContent: '\n ',
+ id: 22,
+ },
+ {
+ type: 2,
+ tagName: 'svg',
+ attributes: {
+ rr_width: '200px',
+ rr_height: '200px',
+ },
+ childNodes: [],
+ isSVG: true,
+ id: 23,
+ },
+ {
+ type: 3,
+ textContent: '\n ',
+ id: 24,
+ },
+ {
+ type: 2,
+ tagName: 'svg',
+ attributes: {
+ style: 'width:200px;height:200px',
+ class: 'sentry-unblock',
+ viewBox: '0 0 80 80',
+ 'data-sentry-unblock': '',
+ },
+ childNodes: [
+ {
+ type: 2,
+ tagName: 'path',
+ attributes: {
+ rr_width: '0px',
+ rr_height: '0px',
+ },
+ childNodes: [],
+ isSVG: true,
+ id: 26,
+ },
+ ],
+ isSVG: true,
+ id: 25,
+ },
+ {
+ type: 3,
+ textContent: '\n ',
+ id: 27,
+ },
+ {
+ type: 2,
+ tagName: 'img',
+ attributes: {
+ rr_width: '100px',
+ rr_height: '100px',
+ },
+ childNodes: [],
+ id: 28,
+ },
+ {
+ type: 3,
+ textContent: '\n ',
+ id: 29,
+ },
+ {
+ type: 2,
+ tagName: 'img',
+ attributes: {
+ 'data-sentry-unblock': '',
+ style: 'width:100px;height:100px',
+ src: 'file:///none.png',
+ },
+ childNodes: [],
+ id: 30,
+ },
+ {
+ type: 3,
+ textContent: '\n ',
+ id: 31,
+ },
+ {
+ type: 3,
+ textContent: '\n\n',
+ id: 32,
+ },
+ ],
+ id: 7,
+ },
+ ],
+ id: 3,
+ },
+ ],
+ id: 1,
+ },
+ initialOffset: {
+ left: 0,
+ top: 0,
+ },
+ });
+});
diff --git a/packages/integration-tests/utils/helpers.ts b/packages/integration-tests/utils/helpers.ts
index 5fb2aafff3e1..82ed49435681 100644
--- a/packages/integration-tests/utils/helpers.ts
+++ b/packages/integration-tests/utils/helpers.ts
@@ -17,8 +17,8 @@ export const envelopeParser = (request: Request | null): unknown[] => {
});
};
-export const envelopeRequestParser = (request: Request | null, envelopeIndex = 2): Event => {
- return envelopeParser(request)[envelopeIndex] as Event;
+export const envelopeRequestParser = (request: Request | null, envelopeIndex = 2): T => {
+ return envelopeParser(request)[envelopeIndex] as T;
};
export const envelopeHeaderRequestParser = (request: Request | null): EventEnvelopeHeaders => {