Skip to content

Commit 86cd7fd

Browse files
authored
fix(replay): Never capture file input changes (#7485)
1 parent 30bba1f commit 86cd7fd

File tree

6 files changed

+91
-5
lines changed

6 files changed

+91
-5
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as Sentry from '@sentry/browser';
2+
import { Replay } from '@sentry/replay';
3+
4+
window.Sentry = Sentry;
5+
window.Replay = new Replay({
6+
flushMinDelay: 200,
7+
flushMaxDelay: 200,
8+
useCompression: false,
9+
maskAllInputs: false,
10+
});
11+
12+
Sentry.init({
13+
dsn: 'https://[email protected]/1337',
14+
sampleRate: 0,
15+
replaysSessionSampleRate: 1.0,
16+
replaysOnErrorSampleRate: 0.0,
17+
18+
integrations: [window.Replay],
19+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
</head>
6+
<body>
7+
<input id="file-input" type="file" />
8+
</body>
9+
</html>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { expect } from '@playwright/test';
2+
import { IncrementalSource } from '@sentry-internal/rrweb';
3+
import type { inputData } from '@sentry-internal/rrweb/typings/types';
4+
5+
import { sentryTest } from '../../../utils/fixtures';
6+
import type { IncrementalRecordingSnapshot } from '../../../utils/replayHelpers';
7+
import {
8+
getIncrementalRecordingSnapshots,
9+
shouldSkipReplayTest,
10+
waitForReplayRequest,
11+
} from '../../../utils/replayHelpers';
12+
13+
function isInputMutation(
14+
snap: IncrementalRecordingSnapshot,
15+
): snap is IncrementalRecordingSnapshot & { data: inputData } {
16+
return snap.data.source == IncrementalSource.Input;
17+
}
18+
19+
sentryTest(
20+
'should not capture file input mutations',
21+
async ({ forceFlushReplay, getLocalTestPath, page, browserName }) => {
22+
// This seems to be flaky on webkit, so skipping there
23+
if (shouldSkipReplayTest() || browserName === 'webkit') {
24+
sentryTest.skip();
25+
}
26+
27+
const reqPromise0 = waitForReplayRequest(page, 0);
28+
const reqPromise1 = waitForReplayRequest(page, 1);
29+
30+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
31+
return route.fulfill({
32+
status: 200,
33+
contentType: 'application/json',
34+
body: JSON.stringify({ id: 'test-id' }),
35+
});
36+
});
37+
38+
const url = await getLocalTestPath({ testDir: __dirname });
39+
40+
await page.goto(url);
41+
42+
await reqPromise0;
43+
44+
await page.setInputFiles('#file-input', {
45+
name: 'file.csv',
46+
mimeType: 'text/csv',
47+
buffer: Buffer.from('this,is,test'),
48+
});
49+
50+
await forceFlushReplay();
51+
52+
const res1 = await reqPromise1;
53+
54+
const snapshots = getIncrementalRecordingSnapshots(res1).filter(isInputMutation);
55+
56+
expect(snapshots).toEqual([]);
57+
},
58+
);

packages/replay/src/util/getPrivacyOptions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export function getPrivacyOptions({
8888
blockSelector,
8989
),
9090
unblockSelector: getOption(unblock, ['.sentry-unblock', '[data-sentry-unblock]']),
91-
ignoreSelector: getOption(ignore, ['.sentry-ignore', '[data-sentry-ignore]'], ignoreClass),
91+
ignoreSelector: getOption(ignore, ['.sentry-ignore', '[data-sentry-ignore]', 'input[type="file"]'], ignoreClass),
9292
};
9393

9494
if (blockClass instanceof RegExp) {

packages/replay/test/integration/rrweb.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ describe('Integration | rrweb', () => {
2020
"blockSelector": ".sentry-block,[data-sentry-block],base[href=\\"/\\"],img,image,svg,video,object,picture,embed,map,audio,link[rel=\\"icon\\"],link[rel=\\"apple-touch-icon\\"]",
2121
"collectFonts": true,
2222
"emit": [Function],
23-
"ignoreSelector": ".sentry-test-ignore,.sentry-ignore,[data-sentry-ignore]",
23+
"ignoreSelector": ".sentry-test-ignore,.sentry-ignore,[data-sentry-ignore],input[type=\\"file\\"]",
2424
"inlineImages": false,
2525
"inlineStylesheet": true,
2626
"maskAllInputs": true,

packages/replay/test/unit/util/getPrivacyOptions.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ describe('Unit | util | getPrivacyOptions', () => {
2020
).toMatchInlineSnapshot(`
2121
Object {
2222
"blockSelector": ".custom-block,.sentry-block,[data-sentry-block],base[href=\\"/\\"]",
23-
"ignoreSelector": ".custom-ignore,.sentry-ignore,[data-sentry-ignore]",
23+
"ignoreSelector": ".custom-ignore,.sentry-ignore,[data-sentry-ignore],input[type=\\"file\\"]",
2424
"maskInputSelector": ".custom-mask,.sentry-mask,[data-sentry-mask]",
2525
"maskTextSelector": ".custom-mask,.sentry-mask,[data-sentry-mask]",
2626
"unblockSelector": ".custom-unblock,.sentry-unblock,[data-sentry-unblock]",
@@ -48,7 +48,7 @@ describe('Unit | util | getPrivacyOptions', () => {
4848
).toMatchInlineSnapshot(`
4949
Object {
5050
"blockSelector": ".custom-block,.deprecated-block-selector,.sentry-block,[data-sentry-block],base[href=\\"/\\"],.deprecated-block-class",
51-
"ignoreSelector": ".custom-ignore,.sentry-ignore,[data-sentry-ignore],.deprecated-ignore-class",
51+
"ignoreSelector": ".custom-ignore,.sentry-ignore,[data-sentry-ignore],input[type=\\"file\\"],.deprecated-ignore-class",
5252
"maskInputSelector": ".custom-mask,.deprecated-mask-selector,.sentry-mask,[data-sentry-mask],.deprecated-mask-class",
5353
"maskTextSelector": ".custom-mask,.deprecated-mask-selector,.sentry-mask,[data-sentry-mask],.deprecated-mask-class",
5454
"unblockSelector": ".custom-unblock,.sentry-unblock,[data-sentry-unblock]",
@@ -74,7 +74,7 @@ describe('Unit | util | getPrivacyOptions', () => {
7474
Object {
7575
"blockClass": /deprecated-block-\\*/,
7676
"blockSelector": ".custom-block,.sentry-block,[data-sentry-block],base[href=\\"/\\"]",
77-
"ignoreSelector": ".custom-ignore,.sentry-ignore,[data-sentry-ignore]",
77+
"ignoreSelector": ".custom-ignore,.sentry-ignore,[data-sentry-ignore],input[type=\\"file\\"]",
7878
"maskInputSelector": ".custom-mask,.sentry-mask,[data-sentry-mask]",
7979
"maskTextClass": /deprecated-mask-\\*/,
8080
"maskTextSelector": ".custom-mask,.sentry-mask,[data-sentry-mask]",

0 commit comments

Comments
 (0)