Repository navigation
release: sync stable to main for version 13.39.2 - #44453
Merged
Merged
Conversation
- chore(assets): add robinhood svg (#44191) ## **Description** Adds the Robinhood brand SVG asset at `app/images/robinhood.svg` for upcoming wallet/provider UI usage. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** 1. N/A — static asset only; no runtime wiring in this PR. ## **Screenshots/Recordings** ### **Before** N/A ### **After** N/A ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] 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-extension/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] > **Low Risk** > Static SVG only; no logic, imports, or behavior changes in this PR. > > **Overview** > Adds a new static brand asset at `app/images/robinhood.svg` (60×60 Robinhood icon on lime `#CCFF00` with rounded corners). > > There is **no application wiring** in this PR—the SVG is intended for follow-up wallet/provider UI work. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit c184dad. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> [d4ce5e4](d4ce5e4) Co-authored-by: @gandalfg <36696601+adaOctopus@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
…eatured network (#44346) - feat(networks): add Robinhood Chain as featured network (#44310) ## **Description** Adds Robinhood Chain (chain ID `0x1237` / 4663) as a featured network in MetaMask Extension. Users can discover and add Robinhood Chain from the network list without manually entering RPC details. Changes in `shared/constants/network.ts`: - Added `CHAIN_IDS.ROBINHOOD_CHAIN` - Added `ROBINHOOD_CHAIN_DISPLAY_NAME` and `ROBINHOOD_CHAIN_IMAGE_URL` - Wired display name, currency (ETH), and image maps - Added `FEATURED_RPCS` entry with Robinhood mainnet RPC and Blockscout explorer ## **Changelog** CHANGELOG entry: Added Robinhood Chain as a featured network ## **Related issues** Fixes: ## **Manual testing steps** 1. Open MetaMask Extension 2. Click the network selector dropdown 3. Browse the featured/popular network list 4. Verify Robinhood Chain appears with the Robinhood logo and ETH as the currency symbol 5. Add Robinhood Chain and verify the RPC connects and the block explorer link works ## **Screenshots/Recordings** ### **Before** Robinhood Chain not present in featured networks list. ### **After** Robinhood Chain appears in featured networks list with correct logo, ETH ticker, and chain ID `0x1237`. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [ ] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). ## **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] > **Low Risk** > Routine featured-network constants and UI list wiring; no changes to auth, signing, or transaction logic beyond exposing a new default RPC URL. > > **Overview** > Adds **Robinhood Chain** (`0x1237`) as a discoverable featured network so users can add it from the network list without manual RPC setup. > > In `shared/constants/network.ts`, the PR introduces `CHAIN_IDS.ROBINHOOD_CHAIN`, display name and `robinhood.svg` branding, and hooks the chain into the usual display name, currency (**ETH**), network image, and native token image maps. A new `FEATURED_RPCS` entry points at `https://rpc.mainnet.chain.robinhood.com` and Blockscout at `https://robinhoodchain.blockscout.com` (custom RPC, no Infura failover). > > `shared/constants/network.test.ts` expects Robinhood in the featured RPC chain ID map, and the network list menu snapshots include the **Additional networks** row for `popular-network-0x1237`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 094a758. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com> [ea6632b](ea6632b) Co-authored-by: @gandalfg <36696601+adaOctopus@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com>
… leak by avoiding `DocumentPictureInPicture` instantiation in Snow hook cp-13.39.2 (#44401) - fix: Fix Firefox detatched-window memory leak by avoiding `DocumentPictureInPicture` instantiation in Snow hook cp-13.39.2 (#44352) ## **Motivation** On Firefox, every closed MetaMask window (popup, notification, home) is retained in memory ([#42891](#42891) and recent internal reports). - **Rate:** ~70 detached window entries (~105MB, fresh test wallet) per popup open/close, linear with use. 30 cycles leave **3.56GB** (13.37.0) / **3.31GB** (13.38.1) of detached documents, surviving forced GC. State-heavy wallets multiply every retained document. - **Mechanism** (heap-graph traced, intervention-tested): Snow's picture-in-picture hook reads `win?.documentPictureInPicture?.requestWindow` in every window. The read lazily instantiates a per-window `DocumentPictureInPicture`, and Firefox's cycle collector fails to break the instance's preserved-wrapper cycle after window close, pinning the entire realm. - **Why now:** Firefox shipped the API in 151 (May 2026). The April-2023 hook was dormant until users auto-updated. The collection failure itself is a Gecko defect (upstream filing in progress; prior art: [Bugzilla 1902438](https://bugzilla.mozilla.org/show_bug.cgi?id=1902438)), but this fix does not depend on Mozilla. ## **Description** Applies the upstream Snow fix ([LavaMoat/snow#171](LavaMoat/snow#171)) as a Yarn patch: the hook moves from the per-window instance to `DocumentPictureInPicture.prototype`, reached through the interface object, which does not invoke the instance-creating getter. - Call semantics unchanged: instance lookup falls through to the patched prototype, `this` stays the instance, same wrapped native. Snow's PiP realm monitoring is preserved. - The patch covers `snow.prod.js` and `snow.js` in addition to `src/request.js`: the extension consumes Snow's prebuilt bundle as a LavaMoat static shim (`LavamoatPlugin`), and webpack never processes `@lavamoat/snow/**`. - **Interim:** remove this patch when `@lavamoat/snow` is bumped to a release containing the upstream fix. The bump is the removal trigger. ## **Cherry-pick candidacy** - Affected population: every Firefox user on 151+ (effectively the whole Firefox base via auto-update). Reproduces from a fresh wallet in five popup opens. No workaround short of a browser restart. - Proposed: next RC, with a hotfix on the current production line worth considering. - Snow is security-team-owned. Their sign-off on shipping a patched Snow is part of this review. ## **Verification** | Check | Result | |---|---| | Intervention: official 13.37.0 artifact, only this hook changed, 30 cycles | **+2,100 docs (3.35GB) → -13 (1.6MB total)**. Hook is the sole delta, so this is also the causal proof | | This PR's CI artifact (`d4dd55f`), probed directly | Patched hook present; 5 cycles: +7 KB-scale entries (1.1MB) vs +345 docs (+534MB) stock | | Field | Original reporter confirms the leak is gone on this PR's CI build | | Independent repro | Manual steps + automated probe: https://github.com/MajorLift/snow/tree/verification/pip-realm-leak/verification | ## **Related issues** Fixes: #42891 ## **Manual testing steps** 1. Install this PR's Firefox build (metamaskbot comment) in a fresh profile via `about:debugging` → Load Temporary Add-on. Onboard with a test SRP. 2. Confirm the fix is live: extension console → `DocumentPictureInPicture.prototype.requestWindow.name` → `"open"` (stock: `"requestWindow"`). 3. Open/close the popup five times, visiting activity or a swap view on a few opens. 4. `about:memory` → Minimize memory usage → Measure → filter `detached`: no `moz-extension` UI-document cohorts (stock: ~70 entries / ~105MB per cycle). ## **Screenshots/Recordings** Heap-graph traces, memory reports, and retaining-path analysis: see the verification bundle above. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. CHANGELOG entry: Fixed a memory leak on Firefox where closed MetaMask windows were retained in memory, growing extension memory use with every popup open [942441b](942441b) Co-authored-by: Jongsun Suh <jongsun.suh@icloud.com>
## **Description**
1. **Split the entry sets.** `nullUnsafeEntries` (`scripts/inpage.js`,
`bootstrap`) run fully outside LavaMoat with no runtime added.
`service-worker.ts` stays in the `unsafe` layer (so its module + static
bootstrap imports are excluded from wrapping) **but** its chunk now runs
in `safe` mode so it carries the LavaMoat runtime.
2. **SES in the SW bundle.** The MV3 SW is self-contained and loads no
shared `runtime` chunk, so `service-worker.js` is added to
`inlineLockdown` — SES is inlined into its own bundle so the wrapped
background has hardened intrinsics + `Compartment`/`harden` available.
3. **Layer boundary at the dynamic import.**
`lavamoatBackgroundLayerRule` re-layers `background.js` (and, by
inheritance, its whole graph) out of `unsafe` into a `background` layer
so it gets wrapped, and `lavamoatUnsafeLayerRule` now `exclude`s
`background.js` so the boundary module itself is wrapped rather than
excluded.
4. **Scuttling on the SW global.** Defense-in-depth parity with the UI
`runtime` and `scripts/contentscript.js` chunks: `scuttleGlobalThis` is
enabled for the SW with an exception list for the globals the
*unwrapped* bootstrap and webpack's `importScripts` chunk loader touch
live after scuttling (`importScripts`, `console`, `performance`, timers,
and the Sentry cluster). Dependency containment does **not** depend on
scuttling — it comes from the Compartments — so wrapped deps still can't
reach the real global regardless.
5. **Policies regenerated.**
`lavamoat/webpack/mv3/{main,flask,beta,experimental}/policy.json` were
regenerated to include the now-wrapped background dependency graph
(~1198 → ~1594 resources). MV2 policies are untouched.
## **Changelog**
CHANGELOG entry: null
## **Related issues**
Fixes: <!-- add the sev1 security ticket link -->
## **Manual testing steps**
1. Build the MV3 Chrome bundle with LavaMoat: `yarn
webpack:lavamoat:build`.
2. Load `dist/chrome` unpacked in Chrome, open the **service worker**
inspector
3. Confirm the service worker installs and reaches `MetaMask
initialization complete` with **no** `inaccessible under scuttling mode`
/ missing-global / policy errors.
4. **Containment check**: temporarily patch a background dependency
(e.g.`node_modules/loglevel/lib/loglevel.js`) with:
```js
console.log('probe', {
clients: typeof globalThis.clients,
registration: typeof globalThis.registration,
serviceWorker: typeof globalThis.serviceWorker,
keyCount: Object.keys(globalThis).length,
});
```
Rebuild, reload, and confirm in the SW console that
`clients`/`registration`/`serviceWorker` are `"undefined"` and
`keyCount` is small (the dep sees its policy-scoped Compartment global).
## **Screenshots/Recordings**
N/A — no UI changes. Behavioral verification is the service-worker
console output described in Manual testing steps.
### **Before**
A background dependency could see globals outside of its intended scope.
### **After**
A wrapped background dependency sees only its Compartment global.
## **Pre-merge author checklist**
- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable <!-- follow-up: regression guard
asserting background.js resolves out of the `unsafe` layer / SW chunks
contain the LavaMoat wrapper -->
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/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]
> **High Risk**
> Changes MV3 extension sandboxing for the service worker and background
(LavaMoat layers, SES lockdown, global scuttling); misconfiguration
could break SW startup or weaken containment.
>
> **Overview**
> Fixes MV3 so **`background.js` and its dependency graph run inside
LavaMoat** instead of inheriting the service worker’s unwrapped `unsafe`
layer.
>
> **Webpack / LavaMoat plugin:** `service-worker.ts` is removed from
fully unwrapped entries but stays on the `unsafe` layer for bootstrap
imports; its chunk now uses **`safe` mode** with an embedded LavaMoat
runtime. **`service-worker.js`** is added to **`inlineLockdown`** (SES
inlined in the SW bundle). A new **`background` webpack layer**
re-layers `app/scripts/background.js` out of `unsafe`, and the unsafe
exclude-loader **`exclude`s** that path so the boundary module is
wrapped. Shared **`scuttleGlobalThis`** exceptions are centralized; the
SW chunk enables scuttling with **`importScripts`** (and shared
exceptions) allowed.
>
> **Tests:** New `plugins.LavamoatPlugin.test.ts` guards layer regexes,
SW `safe` mode, and plugin rule registration.
>
> **Policies:** MV3 `policy.json` (e.g. beta) is regenerated for the
wrapped background graph; **`policy-override.json`** updates across
flavors add entries such as
`@metamask/assets-controllers>@tanstack/query-core`, `centrifuge`, and
gridplus `zod`.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c251e94. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Norbert Elter <72046715+itsyoboieltr@users.noreply.github.com>
Co-authored-by: Howard Braham <howrad@gmail.com>
This PR updates the change log for 13.39.2. (Hotfix - no test plan generated.) --------- Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: Mark Stacey <mark.stacey@consensys.net>
release: 13.39.1
release: 13.39.2
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. |
github-actions
Bot
force-pushed
the
stable-main-13.39.2
branch
from
July 14, 2026 19:06
99890f7 to
3d015e0
Compare
Gudahtt
approved these changes
Jul 14, 2026
Contributor
Author
|
policy-bot: approve |
Contributor
Author
|
Merge my PR |
HowardBraham
approved these changes
Jul 14, 2026
Contributor
Author
|
Merge my PR |
Contributor
|
No release label on PR. Adding release label release-13.41.0 on PR, as PR was added to branch 13.41.0 when release was cut. |
This branch was previously deployed
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Description
This PR syncs the stable branch to main for version 13.39.2.
Synchronization Process:
Fetches the latest changes from the remote repository
Resets the branch to match the stable branch
Attempts to merge changes from main into the branch
Handles merge conflicts if they occur
File Preservation:
Preserves specific files from the stable branch:
CHANGELOG.md
android/app/build.gradle
ios/MetaMask.xcodeproj/project.pbxproj
package.json
Indicates the next version candidate of main to 13.39.2
Changelog
CHANGELOG entry: null
Related issues
Fixes:
Manual testing steps
Screenshots/Recordings
Before
After
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Low Risk
Documentation-only changelog and release-link updates; no application code in this diff.
Overview
Prepares 13.39.2 release notes in
CHANGELOG.mdand refreshes compare links so[Unreleased]tracksv13.39.2...HEAD.Documents 13.39.2 with a Fixed entry for a Firefox memory leak where closed MetaMask popup windows were retained in memory, increasing extension memory use on each popup open (#44352).
Also adds the 13.39.1 section (Added: Robinhood Chain as a featured network, #44346) and new version anchor links for 13.39.1 and 13.39.2.
Reviewed by Cursor Bugbot for commit 3d015e0. Bugbot is set up for automated code reviews on this repo. Configure here.