From 5ce81a198a7b601d672ced2327ca6d1285af0eb1 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Thu, 27 Feb 2025 11:21:09 +0100 Subject: [PATCH 1/3] fix(core): Fix `allowUrls` and `denyUrls` for linked and aggregate exceptions --- .../core/src/integrations/inboundfilters.ts | 13 +- .../lib/integrations/inboundfilters.test.ts | 111 ++++++++++++++++++ 2 files changed, 117 insertions(+), 7 deletions(-) diff --git a/packages/core/src/integrations/inboundfilters.ts b/packages/core/src/integrations/inboundfilters.ts index 7840ab5f6920..072b44d7c5de 100644 --- a/packages/core/src/integrations/inboundfilters.ts +++ b/packages/core/src/integrations/inboundfilters.ts @@ -172,13 +172,12 @@ function _getLastValidUrl(frames: StackFrame[] = []): string | null { function _getEventFilterUrl(event: Event): string | null { try { - let frames; - try { - // @ts-expect-error we only care about frames if the whole thing here is defined - frames = event.exception.values[0].stacktrace.frames; - } catch (e) { - // ignore - } + // If there are linked exceptions or exception aggregates we only want to match against the top frame of the "root" (the main exception) + // The root always comes last in linked exceptions + const rootException = [...(event.exception?.values ?? []).reverse()]?.find( + value => value.mechanism?.parent_id === undefined && value.stacktrace?.frames?.length, + ); + const frames = rootException?.stacktrace?.frames; return frames ? _getLastValidUrl(frames) : null; } catch (oO) { DEBUG_BUILD && logger.error(`Cannot extract url for event ${getEventDescription(event)}`); diff --git a/packages/core/test/lib/integrations/inboundfilters.test.ts b/packages/core/test/lib/integrations/inboundfilters.test.ts index d70a17a81bc7..f9bfbe05e58f 100644 --- a/packages/core/test/lib/integrations/inboundfilters.test.ts +++ b/packages/core/test/lib/integrations/inboundfilters.test.ts @@ -157,10 +157,91 @@ const EXCEPTION_EVENT_WITH_LINKED_ERRORS: Event = { { type: 'ReferenceError', value: '`tooManyTreats` is not defined', + stacktrace: { + frames: [{ filename: 'https://secondary-error.com/' }], + }, + }, + { + type: 'TypeError', + value: 'incorrect type given for parameter `chewToy`: Shoe', + stacktrace: { + frames: [{ filename: 'https://main-error.com/' }], + }, + }, + ], + }, +}; + +const EXCEPTION_EVENT_WITH_AGGREGATE_ERRORS: Event = { + exception: { + values: [ + { + type: 'ReferenceError', + value: '`tooManyTreats` is not defined', + stacktrace: { + frames: [{ filename: 'https://secondary-error.com/' }], + }, + mechanism: { + type: 'generic', + exception_id: 1, + parent_id: 0, + }, }, { type: 'TypeError', value: 'incorrect type given for parameter `chewToy`: Shoe', + stacktrace: { + frames: [{ filename: 'https://main-error.com/' }], + }, + mechanism: { + type: 'generic', + exception_id: 0, + }, + }, + ], + }, +}; + +const EXCEPTION_EVENT_WITH_LINKED_ERRORS_WITHOUT_STACKTRACE: Event = { + exception: { + values: [ + { + type: 'ReferenceError', + value: '`tooManyTreats` is not defined', + stacktrace: { + frames: [{ filename: 'https://main-error.com/' }], + }, + }, + { + type: 'TypeError', + value: 'incorrect type given for parameter `chewToy`: Shoe', + }, + ], + }, +}; + +const EXCEPTION_EVENT_WITH_AGGREGATE_ERRORS_WITHOUT_STACKTRACE: Event = { + exception: { + values: [ + { + type: 'ReferenceError', + value: '`tooManyTreats` is not defined', + stacktrace: { + frames: [{ filename: 'https://secondary-error.com/' }], + }, + mechanism: { + type: 'generic', + exception_id: 1, + parent_id: 0, + }, + }, + { + type: 'TypeError', + value: 'incorrect type given for parameter `chewToy`: Shoe', + mechanism: { + type: 'generic', + exception_id: 0, + }, }, ], }, @@ -615,6 +696,36 @@ describe('InboundFilters', () => { }); expect(eventProcessor(MESSAGE_EVENT_WITH_NATIVE_LAST_FRAME, {})).toBe(null); }); + + it('should apply denyUrls to the "root" error of a linked exception', () => { + const eventProcessor = createInboundFiltersEventProcessor({ + denyUrls: ['https://main-error.com'], + }); + expect(eventProcessor(EXCEPTION_EVENT_WITH_LINKED_ERRORS, {})).toBe(null); + }); + + it('should apply denyUrls to the "root" error of an aggregate exception', () => { + const eventProcessor = createInboundFiltersEventProcessor({ + denyUrls: ['https://main-error.com'], + }); + expect(eventProcessor(EXCEPTION_EVENT_WITH_AGGREGATE_ERRORS, {})).toBe(null); + }); + + it('should apply allowUrls to the "most root" exception in the event if there are exceptions without stacktrace', () => { + const eventProcessor = createInboundFiltersEventProcessor({ + allowUrls: ['https://some-error-that-is-not-main-error.com'], + }); + expect(eventProcessor(EXCEPTION_EVENT_WITH_LINKED_ERRORS_WITHOUT_STACKTRACE, {})).toBe(null); + }); + + it('should not apply allowUrls to the event when the "root" exception of an aggregate error doesn\'t have a stacktrace', () => { + const eventProcessor = createInboundFiltersEventProcessor({ + allowUrls: ['https://some-error-that-doesnt-match-anything.com'], + }); + expect(eventProcessor(EXCEPTION_EVENT_WITH_AGGREGATE_ERRORS_WITHOUT_STACKTRACE, {})).toBe( + EXCEPTION_EVENT_WITH_AGGREGATE_ERRORS_WITHOUT_STACKTRACE, + ); + }); }); describe('useless errors', () => { From 6b28725030a1df8a8bc98fb92b697d63a02d47f5 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Thu, 27 Feb 2025 11:45:31 +0100 Subject: [PATCH 2/3] fix --- packages/core/test/lib/integrations/eventFilters.test.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/core/test/lib/integrations/eventFilters.test.ts b/packages/core/test/lib/integrations/eventFilters.test.ts index c5898136c492..07936f6ad444 100644 --- a/packages/core/test/lib/integrations/eventFilters.test.ts +++ b/packages/core/test/lib/integrations/eventFilters.test.ts @@ -38,7 +38,6 @@ function createEventFiltersEventProcessor( dsn: PUBLIC_DSN, ...clientOptions, defaultIntegrations: false, - // eslint-disable-next-line deprecation/deprecation integrations: [integration], }), ); @@ -707,28 +706,28 @@ describe.each([ }); it('should apply denyUrls to the "root" error of a linked exception', () => { - const eventProcessor = createInboundFiltersEventProcessor({ + const eventProcessor = createEventFiltersEventProcessor(integrationFn, { denyUrls: ['https://main-error.com'], }); expect(eventProcessor(EXCEPTION_EVENT_WITH_LINKED_ERRORS, {})).toBe(null); }); it('should apply denyUrls to the "root" error of an aggregate exception', () => { - const eventProcessor = createInboundFiltersEventProcessor({ + const eventProcessor = createEventFiltersEventProcessor(integrationFn, { denyUrls: ['https://main-error.com'], }); expect(eventProcessor(EXCEPTION_EVENT_WITH_AGGREGATE_ERRORS, {})).toBe(null); }); it('should apply allowUrls to the "most root" exception in the event if there are exceptions without stacktrace', () => { - const eventProcessor = createInboundFiltersEventProcessor({ + const eventProcessor = createEventFiltersEventProcessor(integrationFn, { allowUrls: ['https://some-error-that-is-not-main-error.com'], }); expect(eventProcessor(EXCEPTION_EVENT_WITH_LINKED_ERRORS_WITHOUT_STACKTRACE, {})).toBe(null); }); it('should not apply allowUrls to the event when the "root" exception of an aggregate error doesn\'t have a stacktrace', () => { - const eventProcessor = createInboundFiltersEventProcessor({ + const eventProcessor = createEventFiltersEventProcessor(integrationFn, { allowUrls: ['https://some-error-that-doesnt-match-anything.com'], }); expect(eventProcessor(EXCEPTION_EVENT_WITH_AGGREGATE_ERRORS_WITHOUT_STACKTRACE, {})).toBe( From d7aaf99988933e1908df0a0e045579e28967af2c Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Thu, 27 Feb 2025 12:03:17 +0100 Subject: [PATCH 3/3] size limit --- .size-limit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.size-limit.js b/.size-limit.js index f6f7f342cb0c..ffa69d850947 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -47,7 +47,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/index.js', import: createImport('init', 'browserTracingIntegration', 'replayIntegration'), gzip: true, - limit: '75.1 KB', + limit: '75.2 KB', }, { name: '@sentry/browser (incl. Tracing, Replay) - with treeshaking flags',