Skip to content

release: 13.39.2 - #44395

Merged
sleepytanya merged 5 commits into
stablefrom
release/13.39.2
Jul 14, 2026
Merged

sleepytanya merged 5 commits into
stablefrom
release/13.39.2

Conversation

@metamaskbot

Copy link
Copy Markdown
Collaborator

🚀 v13.39.2 Testing & Release Quality Process

Hi Team,
As part of our new MetaMask Release Quality Process, here’s a quick overview of the key processes, testing strategies, and milestones to ensure a smooth and high-quality deployment.


📋 Key Processes

Testing Strategy

  • Developer Teams:
    Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows.
  • QA Team:
    Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing.
  • Customer Success Team:
    Validate new functionalities and provide feedback to support release monitoring.

GitHub Signoff

  • Each team must sign off on the Release Candidate (RC) via GitHub by the end of the validation timeline (Tuesday EOD PT).
  • Ensure all tests outlined in the Testing Plan are executed, and any identified issues are addressed.

Issue Resolution

  • Resolve all Release Blockers (Sev0 and Sev1) by Tuesday EOD PT.
  • For unresolved blockers, PRs may be reverted, or feature flags disabled to maintain release quality and timelines.

Cherry-Picking Criteria

  • Only critical fixes meeting outlined criteria will be cherry-picked.
  • Developers must ensure these fixes are thoroughly reviewed, tested, and merged by Tuesday EOD PT.

🗓️ Timeline and Milestones

  1. Today (Friday): Begin Release Candidate validation.
  2. Tuesday EOD PT: Finalize RC with all fixes and cherry-picks.
  3. Wednesday: Buffer day for final checks.
  4. Thursday: Submit release to app stores and begin rollout to 1% of users.
  5. Monday: Scale deployment to 10%.
  6. Tuesday: Full rollout to 100%.

✅ Signoff Checklist

Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion:

Team sign-off checklist

  • Extension Platform

This process is a major step forward in ensuring release stability and quality. Let’s stay aligned and make this release a success! 🚀

Feel free to reach out if you have questions or need clarification.

Many thanks in advance

Reference

@github-actions

Copy link
Copy Markdown
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.

@metamask-ci metamask-ci Bot added the team-bots Bot team (for MetaMask Bot, Runway Bot, etc.) label Jul 13, 2026
@socket-security

socket-security Bot commented Jul 13, 2026 •

Copy link
Copy Markdown

No dependency changes detected. Learn more about Socket for GitHub.

👍 No dependency changes detected in pull request

… 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>
Gudahtt and others added 2 commits July 13, 2026 11:03
## **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>
@sleepytanya sleepytanya added the skip-benchmark-gate Disables `run-benchmarks/quality-gate` job label Jul 13, 2026
sleepytanya
sleepytanya previously approved these changes Jul 13, 2026
@metamaskbot
metamaskbot dismissed sleepytanya’s stale review July 13, 2026 15:54

The merge-base changed after approval.

@metamask-ci

metamask-ci Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor
Builds ready [311d329]
Deprecated Browserify fallback builds
⚡ Performance Benchmarks (Total: 🟢 15 pass · 🟡 6 warn · 🔴 3 fail)

Baseline (latest main): 1716549 | Date: 6/29/2026 | Pipeline: 29264189869 | Baseline logs

Metricschrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 openAccountMenuToAccountListLoaded(p95) [CI log]🔴 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]

Regressions (🔴 3 failures)

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🔴 load_new_account
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↓ loadNewAccount/load_new_account: -27%
  • ↓ loadNewAccount/total: -27%
  • ↓ loadNewAccount/inp: -26%
  • ↓ loadNewAccount/fcp: -28%
  • ↓ loadNewAccount/lcp: -17%
  • ↓ confirmTx/longTaskTotalDuration: -18%
  • ↓ confirmTx/longTaskMaxDuration: -22%
  • ↓ confirmTx/tbt: -35%
  • ↓ confirmTx/inp: -18%
  • ↓ confirmTx/fcp: -23%
  • ↓ confirmTx/lcp: -20%
  • ↓ bridgeUserActions/bridge_load_page: -44%
  • ↓ bridgeUserActions/bridge_load_asset_picker: -25%
  • ↓ bridgeUserActions/longTaskCount: -17%
  • ↓ bridgeUserActions/longTaskTotalDuration: -42%
  • ↓ bridgeUserActions/longTaskMaxDuration: -37%
  • ↓ bridgeUserActions/tbt: -86%
  • ↓ bridgeUserActions/inp: -31%
  • ↓ bridgeUserActions/fcp: -21%
  • ↑ loadNewAccount/load_new_account: +553%
  • ↑ loadNewAccount/total: +553%
  • ↓ loadNewAccount/inp: -26%
  • ↑ loadNewAccount/lcp: +1042%
  • ↓ confirmTx/longTaskCount: -100%
  • ↓ confirmTx/longTaskTotalDuration: -100%
  • ↓ confirmTx/longTaskMaxDuration: -100%
  • ↓ confirmTx/tbt: -100%
  • ↑ confirmTx/lcp: +1072%
  • ↑ bridgeUserActions/bridge_load_page: +97%
  • ↑ bridgeUserActions/bridge_load_asset_picker: +77%
  • ↓ bridgeUserActions/longTaskCount: -100%
  • ↓ bridgeUserActions/longTaskTotalDuration: -100%
  • ↓ bridgeUserActions/longTaskMaxDuration: -100%
  • ↓ bridgeUserActions/tbt: -100%
  • ↑ bridgeUserActions/total: +13%
  • ↓ bridgeUserActions/inp: -14%
  • ↑ bridgeUserActions/lcp: +1186%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 loadNewAccount/FCP: p75 1.9s
  • 🟡 confirmTx/FCP: p75 1.8s
  • 🟡 bridgeUserActions/FCP: p75 1.8s
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
–🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↑ startupStandardHome/numNetworkReqs: +15%
  • ↑ startupStandardHome/domInteractive: +58%
  • ↑ startupStandardHome/setupStore: +45%
  • ↑ startupStandardHome/fcp: +55%
  • ↓ startupPowerUserHome/domInteractive: -33%
  • ↓ startupPowerUserHome/backgroundConnect: -34%
  • ↓ startupPowerUserHome/fcp: -30%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/INP: p75 208ms
  • 🟡 startupPowerUserHome/LCP: p75 3.5s
User Journey Benchmarks · Samples: 5 · real API 🔴 3
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 doneButtonToHomeScreen
🔴 total
🔴 [CI log]
🔴 total
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]
🔴 total
assetDetails
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↑ onboardingImportWallet/openAccountMenuToAccountListLoaded: +362%
  • ↑ onboardingImportWallet/longTaskCount: +20%
  • ↑ onboardingImportWallet/longTaskTotalDuration: +36%
  • ↑ onboardingImportWallet/longTaskMaxDuration: +20%
  • ↑ onboardingImportWallet/tbt: +39%
  • ↑ onboardingImportWallet/total: +12%
  • ↑ onboardingNewWallet/longTaskCount: +50%
  • ↑ solanaAssetDetails/cls: +627%
  • ↓ importSrpHome/openAccountMenuAfterLogin: -37%
  • ↑ importSrpHome/homeAfterImportWithNewWallet: +152%
  • ↑ importSrpHome/longTaskCount: +21%
  • ↑ importSrpHome/longTaskTotalDuration: +13%
  • ↑ importSrpHome/total: +122%
  • ↑ importSrpHome/inp: +24%
  • ↓ importSrpHome/lcp: -59%
  • ↓ importSrpHome/cls: -46%
  • ↑ swap/openSwapPageFromHome: +27%
  • ↑ swap/longTaskTotalDuration: +17%
  • ↑ swap/longTaskMaxDuration: +35%
  • ↑ swap/tbt: +58%
  • ↑ swap/lcp: +918%
  • ↑ swap/cls: +168%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 importSrpHome/INP: p75 328ms
  • 🟡 solanaAssetDetails/FCP: p75 1.9s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 3.18 MiB (29.52%)
  • ui: 89.35 KiB (0.52%)
  • common: 0 Bytes (0%)
  • other: 102 Bytes (0.01%)
  • contentScripts: 75.96 KiB (4.15%)
  • zip: 757.22 KiB (2.83%)

AI Test Plan

Risk Score High Risk Medium Risk Files Changed Commits
50/100 5 5 18 7
Cherry-Pick Scenarios (3)

High Risk Scenarios (1)

1. Firefox Detached Window Stability and Memory

Risk Level: HIGH

Why This Matters: Cherry-pick 44401 fixes a Firefox detached-window memory leak by avoiding DocumentPictureInPicture usage; regressions could reintroduce leaks or break window initialization.

Test Steps:

  1. In Firefox, open MetaMask and use Expand view (detached window).
  2. From a dapp, trigger repeated notifications (connect/sign) and open/close them 10–20 times in succession.
  3. Monitor Firefox Task Manager/about:performance to ensure memory does not grow without bound and stabilizes after windows close.
  4. Verify no unresponsive or blank windows appear and the extension remains responsive.

Medium Risk Scenarios (2)

1. Firefox Popup/Detached Window Initialization on First Prompt

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44401 fixes a leak tied to window instantiation; it may affect how the first or subsequent notification windows initialize in Firefox.

Test Steps:

  1. In Firefox, trigger a connect request from a dapp to open the MetaMask notification.
  2. Interact with the notification and, if available, open it as a separate window; complete or reject the request.
  3. Trigger another request immediately and ensure the new window initializes correctly (no white/blank screen) and can be approved.

2. Firefox Long-Running Session Memory Behavior (Detached Window)

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44401 fixes persistent memory growth in Firefox; long-running sessions should no longer leak and must remain stable.

Test Steps:

  1. Keep MetaMask open in a detached window for at least 10 minutes, periodically opening Settings/Activity and completing a few confirmations.
  2. Observe memory/CPU in about:performance to ensure stable usage over time.
  3. Close the detached window and verify memory is released and subsequent prompts still open correctly.

Release Scenarios (7)

High Risk Scenarios (4)

1. Dapp Connection and Provider Injection

Risk Level: HIGH

Why This Matters: LavaMoat policy/plugin changes can block or delay inpage provider injection, breaking basic dapp connectivity.

Test Steps:

  1. Install the extension, create/import a wallet, and navigate to a known EVM dapp (e.g., test-dapp).
  2. Verify window.ethereum is present, then click Connect and approve the connection in MetaMask.
  3. Confirm the connected account address appears on the dapp and persists after a page reload.
  4. Open the same site in a second tab and confirm a proper connection prompt; approve and verify the connected account.
  5. Load an embedded iframe dapp page (if available) and ensure provider is injected and functional.

2. Transaction Confirmation and Sending (ETH transfer)

Risk Level: HIGH

Why This Matters: Runtime sandbox/instrumentation adjustments can disrupt the tx approval UI or background-controller message flow, preventing sends.

Test Steps:

  1. From a connected dapp, initiate an ETH sendTransaction.
  2. In MetaMask, review gas settings and confirm the transaction.
  3. Verify the transaction is submitted, then confirm receipt success in the dapp or a block explorer.
  4. Open Activity in MetaMask and confirm the transaction appears with the expected status.

3. EIP-712 Typed Data Signing (e.g., SIWE)

Risk Level: HIGH

Why This Matters: Policy changes can block content-script <-> background messaging, causing signature prompts to break or return invalid results.

Test Steps:

  1. From the dapp, trigger an EIP-712 (v4) signature request.
  2. In MetaMask, verify the domain, message preview, and account are correct; approve the signature.
  3. Confirm the signature returns to the dapp and validates successfully.
  4. Repeat with a second account to ensure correct account context is used.

4. Concurrent Notifications Handling (Connect/Add Chain/Sign)

Risk Level: HIGH

Why This Matters: Multiple parallel UI surfaces rely on secure bridges; policy or hook updates can cause race conditions and blank modals.

Test Steps:

  1. From a dapp, queue multiple requests in quick succession: connect, addEthereumChain, and a typed-data signature.
  2. Observe that notifications are presented sequentially (no blank/white screens) and are responsive.
  3. Reject one request and approve the rest; verify correct outcomes are reflected in the dapp.
  4. Ensure MetaMask remains responsive and no notifications are lost or stuck.

Medium Risk Scenarios (3)

1. Unlock Flow and Popup State Persistence

Risk Level: MEDIUM

Why This Matters: Hooking/policy changes can disrupt post-unlock routing and state handoff, causing users to lose in-flight actions.

Test Steps:

  1. Lock MetaMask and trigger a dapp action (e.g., connect or sign).
  2. Confirm the unlock screen appears in the popup; enter password and unlock.
  3. Verify the app returns to the pending confirmation seamlessly.
  4. Close and reopen the popup and confirm the pending state persists without data loss.

2. Network Add/Switch via dapp (addEthereumChain/switchEthereumChain)

Risk Level: MEDIUM

Why This Matters: Provider and background message changes can block network prompts or event dispatch, breaking add/switch flows.

Test Steps:

  1. From a dapp, call addEthereumChain for a known test network.
  2. Approve the prompt; verify the new network is added and selected in MetaMask.
  3. From the dapp, call switchEthereumChain to a different network and approve.
  4. Confirm chainChanged fires on the dapp and the network updates in the UI.

3. Account Switching and Events Propagation

Risk Level: MEDIUM

Why This Matters: Instrumentation changes may prevent accountsChanged from propagating, leading to signing/sending from the wrong account.

Test Steps:

  1. Connect a dapp to MetaMask with at least two accounts available.
  2. Switch accounts in MetaMask and verify the dapp receives accountsChanged with the correct address.
  3. Initiate a transaction from the dapp and confirm the from address matches the newly selected account.

Teams Sign-off Status

Signed off: None yet

Awaiting sign-off (6):
Accounts, Confirmations, Networks, Notifications, Transactions, Wallet Integrations


Generated by AI Test Plan Analyzer (gpt-5) at 2026-07-13T16:28:29.208Z

AI generated test plan (JSON): test-plan-13.39.2.json

@metamask-ci

metamask-ci Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor
Builds ready [311d329]
Deprecated Browserify fallback builds
⚡ Performance Benchmarks (Total: 🟢 15 pass · 🟡 6 warn · 🔴 3 fail)

Baseline (latest main): 1716549 | Date: 6/29/2026 | Pipeline: 29264189869 | Baseline logs

Metricschrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 openAccountMenuToAccountListLoaded(p95) [CI log]🔴 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]

Regressions (🔴 3 failures)

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
🔴 load_new_account
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↓ loadNewAccount/load_new_account: -27%
  • ↓ loadNewAccount/total: -27%
  • ↓ loadNewAccount/inp: -26%
  • ↓ loadNewAccount/fcp: -28%
  • ↓ loadNewAccount/lcp: -17%
  • ↓ confirmTx/longTaskTotalDuration: -18%
  • ↓ confirmTx/longTaskMaxDuration: -22%
  • ↓ confirmTx/tbt: -35%
  • ↓ confirmTx/inp: -18%
  • ↓ confirmTx/fcp: -23%
  • ↓ confirmTx/lcp: -20%
  • ↓ bridgeUserActions/bridge_load_page: -44%
  • ↓ bridgeUserActions/bridge_load_asset_picker: -25%
  • ↓ bridgeUserActions/longTaskCount: -17%
  • ↓ bridgeUserActions/longTaskTotalDuration: -42%
  • ↓ bridgeUserActions/longTaskMaxDuration: -37%
  • ↓ bridgeUserActions/tbt: -86%
  • ↓ bridgeUserActions/inp: -31%
  • ↓ bridgeUserActions/fcp: -21%
  • ↑ loadNewAccount/load_new_account: +553%
  • ↑ loadNewAccount/total: +553%
  • ↓ loadNewAccount/inp: -26%
  • ↑ loadNewAccount/lcp: +1042%
  • ↓ confirmTx/longTaskCount: -100%
  • ↓ confirmTx/longTaskTotalDuration: -100%
  • ↓ confirmTx/longTaskMaxDuration: -100%
  • ↓ confirmTx/tbt: -100%
  • ↑ confirmTx/lcp: +1072%
  • ↑ bridgeUserActions/bridge_load_page: +97%
  • ↑ bridgeUserActions/bridge_load_asset_picker: +77%
  • ↓ bridgeUserActions/longTaskCount: -100%
  • ↓ bridgeUserActions/longTaskTotalDuration: -100%
  • ↓ bridgeUserActions/longTaskMaxDuration: -100%
  • ↓ bridgeUserActions/tbt: -100%
  • ↑ bridgeUserActions/total: +13%
  • ↓ bridgeUserActions/inp: -14%
  • ↑ bridgeUserActions/lcp: +1186%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 loadNewAccount/FCP: p75 1.9s
  • 🟡 confirmTx/FCP: p75 1.8s
  • 🟡 bridgeUserActions/FCP: p75 1.8s
Startup Benchmarks · Samples: 100
Benchmarkchrome-webpackfirefox-webpack
startupStandardHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
startupPowerUserHome
[Sentry log · main/release]
–🟡 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↑ startupStandardHome/numNetworkReqs: +15%
  • ↑ startupStandardHome/domInteractive: +58%
  • ↑ startupStandardHome/setupStore: +45%
  • ↑ startupStandardHome/fcp: +55%
  • ↓ startupPowerUserHome/domInteractive: -33%
  • ↓ startupPowerUserHome/backgroundConnect: -34%
  • ↓ startupPowerUserHome/fcp: -30%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 startupPowerUserHome/INP: p75 208ms
  • 🟡 startupPowerUserHome/LCP: p75 3.5s
User Journey Benchmarks · Samples: 5 · real API 🔴 3
Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🔴 [CI log]
🔴 doneButtonToHomeScreen
🔴 total
🔴 [CI log]
🔴 total
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🔴 [CI log]
🔴 total
assetDetails
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]🟡 [CI log]
importSrpHome
[Sentry log · main/release]
🟡 [CI log]🟢 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]

📈 Results compared to the previous 5 runs on main

  • ↑ onboardingImportWallet/openAccountMenuToAccountListLoaded: +362%
  • ↑ onboardingImportWallet/longTaskCount: +20%
  • ↑ onboardingImportWallet/longTaskTotalDuration: +36%
  • ↑ onboardingImportWallet/longTaskMaxDuration: +20%
  • ↑ onboardingImportWallet/tbt: +39%
  • ↑ onboardingImportWallet/total: +12%
  • ↑ onboardingNewWallet/longTaskCount: +50%
  • ↑ solanaAssetDetails/cls: +627%
  • ↓ importSrpHome/openAccountMenuAfterLogin: -37%
  • ↑ importSrpHome/homeAfterImportWithNewWallet: +152%
  • ↑ importSrpHome/longTaskCount: +21%
  • ↑ importSrpHome/longTaskTotalDuration: +13%
  • ↑ importSrpHome/total: +122%
  • ↑ importSrpHome/inp: +24%
  • ↓ importSrpHome/lcp: -59%
  • ↓ importSrpHome/cls: -46%
  • ↑ swap/openSwapPageFromHome: +27%
  • ↑ swap/longTaskTotalDuration: +17%
  • ↑ swap/longTaskMaxDuration: +35%
  • ↑ swap/tbt: +58%
  • ↑ swap/lcp: +918%
  • ↑ swap/cls: +168%

🌐 Core Web Vitals — 🟢 good · 🟡 needs improvement · 🔴 poor (web.dev thresholds)

  • 🟡 importSrpHome/INP: p75 328ms
  • 🟡 solanaAssetDetails/FCP: p75 1.9s
Dapp Page Load Benchmarks · Samples: 100
Benchmarkchrome-webpack
dappPageLoad
[Sentry log · main/release]
🟢 [CI log]
Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 3.18 MiB (29.52%)
  • ui: 89.35 KiB (0.52%)
  • common: 0 Bytes (0%)
  • other: 102 Bytes (0.01%)
  • contentScripts: 75.96 KiB (4.15%)
  • zip: 757.22 KiB (2.83%)

AI Test Plan

Risk Score High Risk Medium Risk Files Changed Commits
24/100 1 2 18 7
Cherry-Pick Scenarios (3)

High Risk Scenarios (1)

1. Firefox notification and popup lifecycle (Connect, Sign, Approve)

Risk Level: HIGH

Why This Matters: Cherry-pick 44401 fixes a Firefox detached-window memory leak by altering the Snow hook; popup lifecycles (connect, sign, approve) are directly impacted and could regress into stuck or phantom windows, broken close behavior, or runtime errors.

Test Steps:

  1. In Firefox, open a dapp (e.g., https://metamask.github.io/test-dapp) and click Connect; approve the connection in the MetaMask popup window.
  2. Trigger a Personal Sign request; reject it and confirm the popup fully closes without leaving a blank or unresponsive window.
  3. Trigger a Signature (eth_signTypedData_v4) and a Transaction approval sequentially; approve both.
  4. Repeat steps 1–3 quickly two more times; observe that each popup opens, renders, and closes cleanly without ghost/zombie windows persisting.
  5. Check the extension background page console for errors referencing DocumentPictureInPicture or Snow/endowment hooks.

Medium Risk Scenarios (2)

1. Transaction confirmation with detached opener (Firefox)

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44401 fixes a Firefox detached-window memory leak; flows where the opener is closed are most susceptible to lifecycle bugs, so we must ensure confirmations still complete and windows close correctly.

Test Steps:

  1. From a dapp in Firefox, initiate an ETH transfer to trigger the MetaMask transaction confirmation window.
  2. While the confirmation window is open, close the originating dapp tab (detaching the confirmation from its opener).
  3. Approve the transaction; verify the confirmation window closes and the transaction appears in Activity with the correct status.
  4. Repeat with a new transaction but Reject; ensure no blank or unresponsive window remains and no error banners appear.

2. Cross-browser regression check for popups (Chromium-based)

Risk Level: MEDIUM

Why This Matters: Cherry-pick 44401 fixes a Firefox-specific issue but changes shared Snow hook behavior; we must verify it introduces no regressions in Chromium-based browsers for popup creation/teardown.

Test Steps:

  1. In Chrome or Edge, perform Connect, Personal Sign, and a Transaction approval from a test dapp, ensuring each popup opens and closes normally.
  2. Rapidly trigger two back-to-back signature requests; reject one and approve the other; confirm correct state updates and no overlapping or orphaned popups.
  3. Check extension/background console for any errors mentioning DocumentPictureInPicture or Snow/endowment hooks.

Teams Sign-off Status

Signed off: None yet

Awaiting sign-off (3):
Confirmations, Notifications, Transactions


Generated by AI Test Plan Analyzer (gpt-5) at 2026-07-13T21:09:55.627Z

AI generated test plan (JSON): test-plan-13.39.2.json

@metamaskbot metamaskbot added the release-13.39.2 Issue or pull request that will be included in release 13.39.2 label Jul 14, 2026
@sleepytanya

Copy link
Copy Markdown
Contributor

Merge my PR

@sleepytanya
sleepytanya merged commit 27ee2a2 into stable Jul 14, 2026
584 of 585 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 14, 2026

This branch was previously deployed

3 inactive deployments
release-branch — 311d3296 Deployed Jul 14, 2026 by sleepytanya via Publish release #39
pr-comment — 311d3296 Deployed Jul 13, 2026 by Gudahtt via Publish prerelease / Publish prerelease #151545
release-ci — 311d3296 Deployed Jul 13, 2026 by Gudahtt via Publish prerelease / Generate AI test plan #151545
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

auto-rc-builds release-13.39.2 Issue or pull request that will be included in release 13.39.2 skip-benchmark-gate Disables `run-benchmarks/quality-gate` job team-bots Bot team (for MetaMask Bot, Runway Bot, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants