Skip to content

Commit 21aac6b

Browse files
committed
improve check for DSN by extracging URL parts
1 parent e638731 commit 21aac6b

File tree

4 files changed

+47
-20
lines changed

4 files changed

+47
-20
lines changed

packages/core/src/utils/isSentryRequestUrl.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Client } from '../client';
22
import type { DsnComponents } from '../types-hoist/dsn';
3+
import { isURLObjectRelative, parseStringToURLObject } from './url';
34

45
/**
56
* Checks whether given url points to Sentry server
@@ -24,9 +25,14 @@ function checkDsn(url: string, dsn: DsnComponents | undefined): boolean {
2425
// Requests to Sentry's ingest endpoint must have a `sentry_key` in the query string
2526
// This is equivalent to the public_key which is required in the DSN
2627
// see https://develop.sentry.dev/sdk/overview/#parsing-the-dsn
27-
// Therefore a request to the same host and with a `sentry_key` in the query string
28-
// can be considered a request to the ingest endpoint
29-
return dsn ? url.includes(dsn.host) && !!url.match(/sentry_key/) : false;
28+
// Therefore, a request to the same host and with a `sentry_key` in the query string
29+
// can be considered a request to the ingest endpoint.
30+
const urlParts = parseStringToURLObject(url);
31+
if (!urlParts || isURLObjectRelative(urlParts)) {
32+
return false;
33+
}
34+
35+
return dsn ? urlParts.host.includes(dsn.host) && /(^|&|\?)sentry_key=/.test(urlParts.search) : false;
3036
}
3137

3238
function removeTrailingSlash(str: string): string {

packages/core/test/lib/utils/isSentryRequestUrl.test.ts

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,46 @@ import type { Client } from '../../../src/client';
44

55
describe('isSentryRequestUrl', () => {
66
it.each([
7-
['http://sentry-dsn.com/my-url?sentry_key=123', 'sentry-dsn.com', '', true],
8-
['http://tunnel:4200', 'sentry-dsn.com', 'http://tunnel:4200', true],
9-
['http://tunnel:4200', 'sentry-dsn.com', 'http://tunnel:4200/', true],
10-
['http://tunnel:4200/', 'sentry-dsn.com', 'http://tunnel:4200', true],
11-
['http://tunnel:4200/', 'another-dsn.com', 'http://tunnel:4200', true],
7+
['http://sentry-dsn.com/my-url?sentry_key=123', 'sentry-dsn.com', ''],
128

13-
['http://tunnel:4200/?sentry_key=123', 'another-dsn.com', '', false],
14-
['http://sentry-dsn.com/my-url', 'sentry-dsn.com', '', false],
15-
['http://sentry-dsn.com', 'sentry-dsn.com', '', false],
16-
['http://tunnel:4200/', 'another-dsn.com', 'http://tunnel:4200/sentry-tunnel', false],
17-
['', 'sentry-dsn.com', '', false],
18-
['http://tunnel:4200/a', 'sentry-dsn.com', 'http://tunnel:4200', false],
19-
])('works with url=%s, dsn=%s, tunnel=%s', (url: string, dsn: string, tunnel: string, expected: boolean) => {
9+
['http://tunnel:4200', 'sentry-dsn.com', 'http://tunnel:4200'],
10+
['http://tunnel:4200', 'sentry-dsn.com', 'http://tunnel:4200/'],
11+
['http://tunnel:4200/', 'sentry-dsn.com', 'http://tunnel:4200'],
12+
['http://tunnel:4200/', 'another-dsn.com', 'http://tunnel:4200'],
13+
])('returns `true` for url=%s, dsn=%s, tunnel=%s', (url: string, dsn: string, tunnel: string) => {
2014
const client = {
2115
getOptions: () => ({ tunnel }),
2216
getDsn: () => ({ host: dsn }),
2317
} as unknown as Client;
2418

25-
// Works with client passed
26-
expect(isSentryRequestUrl(url, client)).toBe(expected);
19+
expect(isSentryRequestUrl(url, client)).toBe(true);
20+
});
21+
22+
it.each([
23+
['http://tunnel:4200/?sentry_key=123', 'another-dsn.com', ''],
24+
['http://sentry-dsn.com/my-url', 'sentry-dsn.com', ''],
25+
['http://sentry-dsn.com', 'sentry-dsn.com', ''],
26+
['http://sAntry-dsn.com/?sentry_key=123', 'sentry-dsn.com', ''],
27+
['http://sAntry-dsn.com/?sAntry_key=123', 'sAntry-dsn.com', ''],
28+
['/ingest', 'sentry-dsn.com', ''],
29+
['/ingest?sentry_key=123', 'sentry-dsn.com', ''],
30+
['/ingest', '', ''],
31+
['', '', ''],
32+
['', 'sentry-dsn.com', ''],
33+
34+
['http://tunnel:4200/', 'another-dsn.com', 'http://tunnel:4200/sentry-tunnel'],
35+
['http://tunnel:4200/a', 'sentry-dsn.com', 'http://tunnel:4200'],
36+
['http://tunnel:4200/a', '', 'http://tunnel:4200/'],
37+
])('returns `false` for url=%s, dsn=%s, tunnel=%s', (url: string, dsn: string, tunnel: string) => {
38+
const client = {
39+
getOptions: () => ({ tunnel }),
40+
getDsn: () => ({ host: dsn }),
41+
} as unknown as Client;
42+
43+
expect(isSentryRequestUrl(url, client)).toBe(false);
44+
});
45+
46+
it('handles undefined client', () => {
47+
expect(isSentryRequestUrl('http://sentry-dsn.com/my-url?sentry_key=123', undefined)).toBe(false);
2748
});
2849
});

packages/replay-internal/test/integration/shouldFilterRequest.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ describe('Integration | shouldFilterRequest', () => {
2020
it('should filter requests for Sentry ingest URLs', async () => {
2121
const { replay } = await mockSdk();
2222

23-
expect(shouldFilterRequest(replay, 'https://03031aa.ingest.f00.f00/api/129312/')).toBe(true);
23+
expect(shouldFilterRequest(replay, 'https://03031aa.ingest.f00.f00/api/129312/?sentry_key=123')).toBe(true);
2424
});
2525
});

packages/vercel-edge/test/wintercg-fetch.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ describe('WinterCGFetch instrumentation', () => {
102102
expect(fetchInstrumentationHandlerCallback).toBeDefined();
103103

104104
const startHandlerData: HandlerDataFetch = {
105-
fetchData: { url: 'https://dsn.ingest.sentry.io/1337', method: 'POST' },
106-
args: ['https://dsn.ingest.sentry.io/1337'],
105+
fetchData: { url: 'https://dsn.ingest.sentry.io/1337?sentry_key=123', method: 'POST' },
106+
args: ['https://dsn.ingest.sentry.io/1337?sentry_key=123'],
107107
startTimestamp: Date.now(),
108108
};
109109
fetchInstrumentationHandlerCallback(startHandlerData);

0 commit comments

Comments
 (0)