fix(connect): clean up leaked onConnect/WebUSB/BroadcastChannel listeners#28242
Draft
mroz22 wants to merge 3 commits into
Draft
fix(connect): clean up leaked onConnect/WebUSB/BroadcastChannel listeners#28242mroz22 wants to merge 3 commits into
mroz22 wants to merge 3 commits into
Conversation
`ServiceWorkerWindowChannel.connect()` never removed the `chrome.runtime.onConnect` listener in `disconnect()` and had no guard against duplicate registration. Audit 18 additional packages (transport, connect-web, connect-common, suite-desktop-native, websocket-client, blockchain-link, request-manager, connect-mobile) with 18 new false positives documented in reports.
`WebUSB` setters in `react-native-usb/src/index.ts` now store the `EventSubscription` returned by `ReactNativeUsbModule.addListener()` and call `.remove()` on overwrite or null assignment. Audit 8 additional packages (suite-desktop-api, trezor-user-env-link, transport-native-usb, connect-cli, react-native-usb/ios, components) with 9 new false positives documented in reports.
In `connect-explorer/trezorConnectActions.ts` each repeated `init()` call in deeplink mode created a new BroadcastChannel without closing the previous one. Audit connect-explorer and connect-examples as false positives.
2 tasks
Contributor
Author
|
CI Maintenance — 2026-06-02 All CI checks green. No reviews detected. Actions taken this session:
Generated by Claude Code |
There was a problem hiding this comment.
Pull request overview
Three small, independently revertible listener/subscription cleanup fixes split out of the broader leak audit in #27978. Each adds the missing teardown for a long-lived listener so repeated init()/connect() no longer stack handlers.
Changes:
ServiceWorkerWindowChannel.connect()stores thechrome.runtime.onConnectcallback, guards against duplicate registration, and removes it indisconnect().WebUSB.onconnect/ondisconnectsetters now store the returnedEventSubscription,.remove()the previous one on overwrite, and acceptnullto clear.trezorConnectActions.init()closes the previous deeplinkBroadcastChannelbefore creating a new one.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/connect-common/src/messageChannel/serviceworker-window.ts | Track onConnect listener as an instance field; guard duplicate registration; remove in disconnect(). |
| packages/react-native-usb/src/index.ts | Store and dispose EventSubscription returned by onDeviceConnected/onDeviceDisconnect; accept null to clear. |
| packages/connect-explorer/src/actions/trezorConnectActions.ts | Close the previous module-scoped BroadcastChannel before creating a new one on re-init. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This was referenced Jun 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three isolated listener / subscription leak fixes, split out of the broader audit in #27978 so they can be reviewed independently. Each touches a single file in a distinct package and adds the missing cleanup.
Fixes
@trezor/connect-common—ServiceWorkerWindowChannelconnect()added achrome.runtime.onConnectlistener via an inline closure that was never removed.onConnectis a global Chrome event (unlikeport.onMessage, which is port-scoped), so the leaked closure survived the whole extension lifetime and re-connect()stacked more. Now the listener is stored on the instance, registration is guarded against duplicates, anddisconnect()removes it.@trezor/react-native-usb—WebUSBset onconnect/set ondisconnectcalledonDeviceConnected/Disconnect()without storing the returnedEventSubscription, so reassigning a handler leaked the native Android/iOS listener and assigningnullregistered a broken callback instead of removing. Setters now.remove()the previous subscription and acceptnullto clear.@trezor/connect-explorer—trezorConnectActions.init()Deeplink mode created a new
BroadcastChannel('trezor_connect_callback')on everyinit()without closing the previous one.BroadcastChannelstays registered internally untilclose(), so repeated init stacked channels that all replied to every callback URL. Now the previous channel is closed before a new one is created.Why split out
Three single-file, single-concern fixes in packages no other PR in the leak-audit stream touches. Each is trivially reviewable and independently revertible.
Related PRs (listener-leak audit stream)
fix: audit and patch event listener leaks across transport/connect/desktop packages(origin of these commits)fix(suite-desktop): clean up accumulated Electron listeners on re-init(sibling split-out: the two desktop fixes)feat(utils): introduce listener disposer helper for Connect/transport sitesTest plan
lint:jsclean on all three changed files🤖 Generated with Claude Code
🌐 Preview deployments
🌐 Suite Web preview: https://dev.suite.sldev.cz/suite-web/mroz22/isolated-listener-leaks/web/
🔍 Currents Test Results
🔍 Suite web test results: View in Currents
🔒 Quarantined E2E Tests
Trezor Suite (web) — 10 test(s)
Updated: 2026-06-01T15:08:09.674Z • 10 test(s) total