Skip to content

Conversation

@jiexi
Copy link
Contributor

@jiexi jiexi commented Dec 21, 2025

Description

Improve SDK and WalletConnect connection reliability

Changelog

CHANGELOG entry: null

Related issues

Fixes:

Manual testing steps

Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]

Screenshots/Recordings

Before

After

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Blocks connections when origin/url/title equals 'metamask' (not substrings) in SDK/WalletConnect flows and adds tests.

  • Security/Origin Validation:
    • SDK Deeplink: In DeeplinkProtocolService.setupBridge, reject clients whose originatorInfo.url or title equals ORIGIN_METAMASK; keep normal bridge setup otherwise.
    • SDK Handler: In handlers/setupBridge, add the same rejection before creating BackgroundBridge.
    • SDKConnectV2: In services/connection-registry.handleConnectDeeplink, block requests when metadata.dapp.url or name equals ORIGIN_METAMASK.
    • WalletConnect v2:
      • During init, skip restoring sessions with peer.metadata.url === ORIGIN_METAMASK.
      • On session_proposal, reject when metadata.url === ORIGIN_METAMASK.
  • Tests:
    • Add unit tests covering rejection for exact metamask origins and allowing substrings/valid URLs in DeeplinkProtocolService.test.ts, handlers/setupBridge.test.ts, and connection-registry.test.ts (WC2 origin rejection tests added but skipped).
  • Misc:
    • Import ORIGIN_METAMASK where needed; minor import consolidation with toChecksumHexAddress.

Written by Cursor Bugbot for commit 95cb249. This will update automatically on new commits. Configure here.

sethkfman and others added 2 commits December 21, 2025 12:48
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

Fixes:

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

<!-- [screenshots/recordings] -->

<!-- [screenshots/recordings] -->

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> <sup>[Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) is
generating a summary for commit
bc90da8. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Nicholas Ellul <15018469+NicholasEllul@users.noreply.github.com>
Co-authored-by: Jiexi Luan <jiexiluan@gmail.com>
@jiexi jiexi requested a review from a team as a code owner December 21, 2025 20:51
@github-actions
Copy link
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbot metamaskbot added the team-wallet-integrations Wallet Integrations team label Dec 21, 2025
@jiexi jiexi changed the title jl/update chore: improve SDK and WalletConnect connection reliability Dec 21, 2025
@jiexi jiexi added the no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed label Dec 21, 2025
)}`;

await registry.handleConnectDeeplink(blockedDeeplink);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test has no assertions and always passes

The test 'blocks connection requests with \metamask` as dapp name'has no assertions after callinghandleConnectDeeplink. Unlike the similar test above it (lines 604-632) which properly asserts showConnectionError, Connection.createnot called, andsave` not called, this test executes the code but never verifies the expected behavior. This means the test will always pass regardless of whether the security check actually works, providing no regression protection for the dapp name blocking feature.

Fix in Cursor Fix in Web

expect(service.bridgeByClientId[clientInfo.clientId]).toBeInstanceOf(
BackgroundBridge,
);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test names use prohibited "should" prefix (Bugbot Rules)

The unit testing guidelines explicitly state "NEVER use 'should' in test names - this is a hard rule with zero exceptions." The newly added tests use names like 'should throw error when originatorInfo.url is "metamask"', 'should allow connection when originatorInfo contains "metamask" as substring', and 'should reject session proposal with "metamask" origin'. These violate the naming convention and should use action-oriented descriptions instead.

Additional Locations (2)

Fix in Cursor Fix in Web

reason: getSdkError('USER_REJECTED_METHODS'),
});
return;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WalletConnect origin check misses name/title validation

The WalletConnectV2.ts origin validation only checks if url === ORIGIN_METAMASK, but the other three implementations in this PR (DeeplinkProtocolService.ts, setupBridge.ts, connection-registry.ts) consistently check both url AND title/name fields. This inconsistency means a malicious dapp could set metadata.name to 'metamask' while using a different URL, which would be blocked by SDK Connect but allowed through WalletConnect, creating a security gap.

Additional Locations (1)

Fix in Cursor Fix in Web

…ion` scenario (#24216)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Fixes tsc lint errors in the WalletConnectV2 tests. Additionally skips
the newly added `Origin Rejection` scenario due to state from another
test that seems to be bleeding into `should reject session proposal with
"metamask" origin` and causing it to fail

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Skips the Origin Rejection test suite and updates WalletConnect v2
test payloads to include required fields for TSC/unit tests.
> 
> - **Tests (WalletConnect v2)**:
> - *Origin Rejection*: Mark `describe('Origin Rejection')` as
`describe.skip` to disable the suite.
> - *Test Payloads*: Add required fields to session proposals/requests
(`params.id`, `pairingTopic`, `proposer.publicKey`, `expiryTimestamp`,
`relays`, `verifyContext`) to satisfy type expectations and stabilize
tests.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3357b77. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
});
});

describe.skip('Origin Rejection', () => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipped tests leave origin rejection feature untested

The describe.skip('Origin Rejection', ...) prevents all origin rejection tests from running. This means the new security feature that blocks connections from metamask origin in WalletConnectV2.ts (lines 445-452) has no test coverage. The skip modifier causes Jest to ignore this entire test suite, leaving the feature unverified.

Fix in Cursor Fix in Web

expect(service.bridgeByClientId[clientInfo.clientId]).toBeInstanceOf(
BackgroundBridge,
);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test names use "should" violating guidelines (Bugbot Rules)

Multiple new tests use "should" in their names, violating the unit testing guidelines rule: "NEVER use 'should' in test names - this is a hard rule with zero exceptions". Examples include should throw error when originatorInfo.url is "metamask", should allow connection when originatorInfo contains "metamask" as substring, and should reject session proposal with "metamask" origin. Tests should use action-oriented descriptions like throws error when originatorInfo.url is "metamask".

Additional Locations (2)

Fix in Cursor Fix in Web

@github-actions
Copy link
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeCore, SmokeMultiChainPermissions, SmokeConfirmationsRedesigned
  • Risk Level: high
  • AI Confidence: 75%
click to see 🤖 AI reasoning details

This PR implements a security fix that blocks connections from external sources claiming to be from the "metamask" origin (ORIGIN_METAMASK). The changes span multiple critical connection handling modules:

  1. DeeplinkProtocolService.ts - Adds validation to reject deeplink connections where originatorInfo.url or title equals "metamask"
  2. setupBridge.ts - Blocks bridge setup for connections claiming metamask origin
  3. connection-registry.ts (SDKConnectV2) - Blocks connection requests with metamask as dapp.url or dapp.name
  4. WalletConnectV2.ts - Rejects WalletConnect session proposals with "metamask" URL and skips invalid sessions during init

This is a security-focused change that prevents potential origin spoofing attacks. The changes are in critical app/core/ paths that handle all external dApp connections.

Tag Selection Rationale:

  • SmokeCore: Essential because these changes affect core wallet connectivity, deeplink handling, and SDK/WalletConnect connection protocols - fundamental to how the app communicates with external dApps
  • SmokeMultiChainPermissions: The changes involve permission-related code (PermissionController imports, CAIP-25 permission handling) and affect how connections are authorized
  • SmokeConfirmationsRedesigned: WalletConnect and SDK connections ultimately lead to transaction confirmations; ensuring the connection flow works correctly is critical for confirmation flows

The unit tests added are comprehensive, but E2E testing is important to verify that legitimate dApp connections still work correctly while malicious origin spoofing is blocked.

View GitHub Actions results

@sonarqubecloud
Copy link

Copy link
Contributor

@abretonc7s abretonc7s left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tested and it works on sdk but bugbots are legits and should be addressed first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed size-M team-wallet-integrations Wallet Integrations team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants