Skip to content

Conversation

@weitingsun
Copy link
Contributor

@weitingsun weitingsun commented Dec 24, 2025

Description

Merge 7.61.3, 7.61.4 and 7.61.5 back to main

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

Strengthens origin validation for external requests and expands hardware auto-signing.

  • Rejects external eth_sendTransaction and connections using internal origins via checks in eth_sendTransaction, WalletConnect (session proposal/init and sendTransaction), SDKConnect (bridge setup, deeplink protocol, V2 connection registry), and deeplink handlers; surfaces invalidParams/errors
  • Normalizes channelId handling in deeplink flows and guards against internal-origin channel IDs
  • Adds comprehensive tests covering blocked/allowed origins for SDK deeplink protocol, SDK V2 connection registry, and WalletConnect V2
  • Expands auto-sign to include QR hardware accounts in RootRPCMethodsUI (in addition to Ledger)

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

@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-mobile-platform Mobile Platform team label Dec 24, 2025
@weitingsun weitingsun marked this pull request as ready for review December 24, 2025 02:56
@weitingsun weitingsun requested a review from a team as a code owner December 24, 2025 02:56
)}`;

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 missing assertions for blocked metamask dapp name

The test blocks connection requests with 'metamask' as dapp name lacks any expect assertions. Unlike the preceding test for blocking metamask as origin (which includes three assertions), this test only calls handleConnectDeeplink without verifying the behavior. The test will always pass regardless of whether the blocking logic works correctly.

Fix in Cursor Fix in Web

<!--
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.
-->

Dapp connection implementaion robustness
<!--
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]
> Strengthens origin validation to prevent external dapps from using
internal MetaMask origins.
>
> - Enforces `INTERNAL_ORIGINS` checks and throws
`rpcErrors.invalidParams` in `eth_sendTransaction`, SDK deeplink
`processDappRpcRequest`, SDK `setupBridge`, SDKConnectV2
`handleConnectDeeplink`, WC2 `onSessionProposal`, and WC2 session
`handleSendTransaction`.
> - Normalizes use of origin/hostname where needed and persists origin
metadata for UI as before.
> - Updates WC2 tests: stubs `rejectSession` to resolve, adds
comprehensive origin-rejection cases (blocks plain `metamask`, allows
valid URLs including subdomains and `metamask.io`).
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
bd6a404. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
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)

Multiple new tests use "should" in their names (e.g., 'should throw error when originatorInfo.url is "metamask"'). This violates the Unit Testing Guidelines rule: "NEVER use 'should' in test names - this is a hard rule with zero exceptions." Test names like 'throws error when originatorInfo.url equals metamask' would be compliant.

Additional Locations (2)

Fix in Cursor Fix in Web

throw rpcErrors.invalidParams({
message: 'External transactions cannot use internal origins',
});
}
Copy link

Choose a reason for hiding this comment

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

Undefined values may incorrectly match INTERNAL_ORIGINS array

The INTERNAL_ORIGINS array includes process.env.MM_FOX_CODE, which is undefined when the env var is not set. The new INTERNAL_ORIGINS.includes() checks don't guard against undefined input values, unlike the earlier === ORIGIN_METAMASK checks which use truthiness guards (originatorInfo.url &&). If both the env var is unset and originatorInfo.url/title or params.url is undefined (e.g., from a malformed dapp request), includes(undefined) would return true, incorrectly blocking legitimate connections.

Additional Locations (2)

Fix in Cursor Fix in Web

@weitingsun weitingsun requested a review from a team as a code owner December 24, 2025 04:18
@weitingsun weitingsun changed the title chore: merge 7.61.3 to main chore: merge release to main Dec 24, 2025
handled();
if (params.channelId && INTERNAL_ORIGINS.includes(params.channelId)) {
throw new Error('External transactions cannot use internal origins');
}
Copy link

Choose a reason for hiding this comment

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

Security check validates wrong field in deeplink handlers

The security check validates params.channelId against INTERNAL_ORIGINS, but channelId is a session identifier (typically a UUID), not an origin URL. The error message says "External transactions cannot use internal origins" which is misleading since channelId is not an origin. Compare with other files in this PR that correctly check origin fields: eth_sendTransaction.ts checks hostname, DeeplinkProtocolService.ts checks params.url, setupBridge.ts checks originatorInfo.url. The actual dApp origin information in these handlers is in params.originatorInfo (parsed later), not channelId. This check provides incomplete protection against internal origin spoofing.

Additional Locations (1)

Fix in Cursor Fix in Web

@weitingsun weitingsun added the skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. label Dec 24, 2025
@github-actions github-actions bot added size-L and removed size-M labels Dec 24, 2025
@github-actions
Copy link
Contributor

🔍 Smart E2E Test Selection

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

This PR implements critical security hardening to prevent external connections (WalletConnect, SDK, deeplinks) from spoofing internal MetaMask origins. The changes span multiple core modules:

  1. Security validation added across all external connection entry points:

    • WalletConnect V2 session proposals and connections
    • SDK deeplink protocol service
    • SDK V2 connection registry
    • Legacy deeplink handlers (connectWithWC, handleMetaMaskDeeplink)
    • eth_sendTransaction RPC method
    • Bridge setup for SDK connections
  2. New INTERNAL_ORIGINS constant blocks connections claiming to be from:

    • ORIGIN_METAMASK ('metamask')
    • TransactionTypes.MMM
    • process.env.MM_FOX_CODE
  3. RootRPCMethodsUI.js change restricts auto-signing to only Ledger and QR hardware accounts, adding an additional security layer.

  4. Comprehensive unit tests added for all new validation logic.

Tag Selection Rationale:

  • SmokeCore: Core wallet functionality, app state, and navigation are affected by these fundamental security changes to connection handling
  • SmokeConfirmationsRedesigned: Transaction confirmation flows are directly impacted by the eth_sendTransaction changes and the RootRPCMethodsUI auto-sign restriction
  • SmokeWalletPlatform: Core wallet operations, account handling, and network switching could be affected by the connection validation changes
  • SmokeMultiChainPermissions: Permission management and multi-chain connections are directly affected since the changes validate origins during permission requests and connection establishment

This is a high-risk change because it modifies security-critical code paths that handle external dApp connections and transaction processing. While the changes are defensive (blocking malicious origins), any regression could either break legitimate dApp connections or fail to properly block malicious ones.

View GitHub Actions results

)}`;

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 missing assertions for dapp name blocking (Bugbot Rules)

The test 'blocks connection requests with \metamask` as dapp name'has no assertions after callinghandleConnectDeeplink. The preceding test (lines 604-631) for blocking by URL includes three assertions (showConnectionError, Connection.createnot called,mockStore.save` not called), but this test simply ends after the Act phase. This violates the mandatory AAA (Arrange, Act, Assert) pattern from the unit testing guidelines and means the test won't detect regressions if the dapp name blocking logic breaks.

Fix in Cursor Fix in Web

.mockResolvedValue(undefined);
});

it('should reject session proposal with "metamask" origin', async () => {
Copy link

Choose a reason for hiding this comment

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

Tests use prohibited "should" in names (Bugbot Rules)

Multiple new tests violate the unit testing guidelines rule: "NEVER use 'should' in test names - this is a hard rule with zero exceptions." Tests like 'should throw error when originatorInfo.url is "metamask"', 'should reject session proposal with "metamask" origin', and similar patterns across WalletConnectV2.test.ts, DeeplinkProtocolService.test.ts, and setupBridge.test.ts all use "should" at the start of their names. These need to be rewritten with action-oriented descriptions (e.g., 'throws error when originatorInfo.url is metamask').

Additional Locations (2)

Fix in Cursor Fix in Web

Copy link
Contributor

@Cal-L Cal-L left a comment

Choose a reason for hiding this comment

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

LGTM

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
59.3% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

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

Labels

size-L skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. team-mobile-platform Mobile Platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants