Skip to content

Commit 89a359d

Browse files
committed
fix(replay): Never capture file input changes
1 parent 7aa20d0 commit 89a359d

File tree

6 files changed

+87
-5
lines changed

6 files changed

+87
-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: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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('should not capture file input mutations', async ({ forceFlushReplay, getLocalTestPath, page }) => {
20+
if (shouldSkipReplayTest()) {
21+
sentryTest.skip();
22+
}
23+
24+
const reqPromise0 = waitForReplayRequest(page, 0);
25+
const reqPromise1 = waitForReplayRequest(page, 1);
26+
27+
await page.route('https://dsn.ingest.sentry.io/**/*', route => {
28+
return route.fulfill({
29+
status: 200,
30+
contentType: 'application/json',
31+
body: JSON.stringify({ id: 'test-id' }),
32+
});
33+
});
34+
35+
const url = await getLocalTestPath({ testDir: __dirname });
36+
37+
await page.goto(url);
38+
39+
await reqPromise0;
40+
41+
await page.setInputFiles('#file-input', {
42+
name: 'file.csv',
43+
mimeType: 'text/csv',
44+
buffer: Buffer.from('this,is,test'),
45+
});
46+
47+
await forceFlushReplay();
48+
49+
const res1 = await reqPromise1;
50+
51+
const snapshots = getIncrementalRecordingSnapshots(res1).filter(isInputMutation);
52+
53+
expect(snapshots).toEqual([]);
54+
});

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)