Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions packages/worker/client/sentry-browser-filters.node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
filterBrowserInjectedGlobalNoiseSentryEvent,
filterBrowserSentryEvent,
filterChromeExtensionObjectNotFoundSentryEvent,
filterChromeExtensionReceivingEndMissingSentryEvent,
filterFathomRemoveChildNullSentryEvent,
filterFirefoxDomPermissionDeniedSentryEvent,
filterMetaMaskExtensionSentryEvent,
Expand Down Expand Up @@ -216,6 +217,59 @@ test('browser Sentry filters drop AbortError and Firefox Xray noise and keep rea
}),
).toBeNull()

// Chrome extension receiving-end missing (issue 7662064169 / KODY-CLOUDFLARE-4F).
expect(
filterChromeExtensionReceivingEndMissingSentryEvent({
exception: {
values: [
{
type: 'Error',
value:
'Could not establish connection. Receiving end does not exist.',
},
],
},
}),
).toBeNull()
expect(
filterChromeExtensionReceivingEndMissingSentryEvent(
{
exception: {
values: [{ type: 'Error', value: 'something else' }],
},
},
new Error(
'Could not establish connection. Receiving end does not exist.',
),
),
).toBeNull()
expect(
filterBrowserSentryEvent({
exception: {
values: [
{
type: 'Error',
value:
'Error: Could not establish connection. Receiving end does not exist.',
},
],
},
}),
).toBeNull()
// Nearby connection wording from app code must not be dropped.
expect(
filterChromeExtensionReceivingEndMissingSentryEvent({
exception: {
values: [
{
type: 'Error',
value: 'Could not establish connection to the MCP server.',
},
],
},
}),
).not.toBeNull()

// MetaMask inpage.js session restore (issue 7658961865 / KODY-CLOUDFLARE-3X).
expect(
filterMetaMaskExtensionSentryEvent({
Expand Down
61 changes: 61 additions & 0 deletions packages/worker/client/sentry-browser-filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,59 @@ export function filterChromeExtensionObjectNotFoundSentryEvent<
return event
}

/**
* Chrome/Firefox extension messaging noise: content scripts and page-injected
* extension code call `chrome.runtime.sendMessage` / `browser.runtime.sendMessage`
* when the extension's background/service worker (or another receiving end) is
* gone — unloaded, updated, or never registered for that tab. Chromium rejects
* with this exact IPC wording. The promise often surfaces on the host page with
* no app stack frames (Sentry attributes the culprit to the document URL).
*
* Signature from production issue 7662064169 / KODY-CLOUDFLARE-4F (Chrome on
* https://heykody.app/, zero frames, handled generic capture). Kody never uses
* `chrome.runtime` / `browser.runtime`. Match is intentionally narrow: only
* this exact "Could not establish connection. Receiving end does not exist"
* wording (optional `Error:` preface). Never blanket-drop connection errors.
*/
const chromeExtensionReceivingEndMissingMessage =
/^(?:Error:\s*)?Could not establish connection\. Receiving end does not exist\.?$/

export function isChromeExtensionReceivingEndMissingMessage(message: string) {
return chromeExtensionReceivingEndMissingMessage.test(message.trim())
}

export function isChromeExtensionReceivingEndMissingError(error: unknown) {
if (typeof error === 'string') {
return isChromeExtensionReceivingEndMissingMessage(error)
}
if (typeof error !== 'object' || error === null) return false
if (!('message' in error) || typeof error.message !== 'string') return false
return isChromeExtensionReceivingEndMissingMessage(error.message)
}

export function isChromeExtensionReceivingEndMissingSentryEvent(
event: SentryErrorEventLike,
originalException?: unknown,
) {
if (isChromeExtensionReceivingEndMissingError(originalException)) return true
return sentryEventMessages(event).some(
(message) =>
typeof message === 'string' &&
isChromeExtensionReceivingEndMissingMessage(message),
)
}

export function filterChromeExtensionReceivingEndMissingSentryEvent<
T extends SentryErrorEventLike,
>(event: T, originalException?: unknown): T | null {
if (
isChromeExtensionReceivingEndMissingSentryEvent(event, originalException)
) {
return null
}
return event
}

/**
* MetaMask (`chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/…`) injects
* `inpage.js` into every page and tries to restore a wallet session on load.
Expand Down Expand Up @@ -536,6 +589,14 @@ export function filterBrowserSentryEvent<T extends SentryErrorEventLike>(
) {
return null
}
if (
filterChromeExtensionReceivingEndMissingSentryEvent(
event,
originalException,
) === null
) {
return null
}
if (filterMetaMaskExtensionSentryEvent(event, originalException) === null) {
return null
}
Expand Down
15 changes: 8 additions & 7 deletions packages/worker/client/sentry-init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ export function initBrowserSentry(config: SentryClientConfig) {
// permission-denied from Replay/hydration on restricted nodes,
// injected wallet/`__firefox__` globals, Fathom beacon
// removeChild-on-null, Chrome extension IPC "Object Not Found
// Matching Id…", MetaMask inpage connect failures, Twitter/X
// in-app browser chrome `CONFIG` ReferenceErrors, and injected
// unguarded `meta[property='og:type']` probes from `global code`) —
// see filterBrowserSentryEvent / KODY-CLOUDFLARE-23 /
// Matching Id…", Chrome/Firefox extension "Receiving end does not
// exist", MetaMask inpage connect failures, Twitter/X in-app browser
// chrome `CONFIG` ReferenceErrors, and injected unguarded
// `meta[property='og:type']` probes from `global code`) — see
// filterBrowserSentryEvent / KODY-CLOUDFLARE-23 /
// KODY-CLOUDFLARE-3Q / KODY-CLOUDFLARE-3S / KODY-CLOUDFLARE-3X /
// KODY-CLOUDFLARE-43 / KODY-CLOUDFLARE-46 / issues 7639685398,
// 7648833360, 7648833403, 7653117289, 7655189301, 7658961865,
// 7659616372, 7660258027.
// KODY-CLOUDFLARE-43 / KODY-CLOUDFLARE-46 / KODY-CLOUDFLARE-4F /
// issues 7639685398, 7648833360, 7648833403, 7653117289, 7655189301,
// 7658961865, 7659616372, 7660258027, 7662064169.
beforeSend(event, hint) {
return filterBrowserSentryEvent(event, hint.originalException)
},
Expand Down
Loading