MetaMask / MetaMask/metamask-extension

[Bug]: Onboarding talks to Bitcoin/Tron Infura, price API, and Shield before Done under max privacy

Open
#45,665 0 comments 0 reactions 0 assignees View on GitHub
area-onboarding area-privacy INVALID-ISSUE-TEMPLATE team-networks type-bug
Dominant language
TypeScript
Stars
13.2k
Forks
5.6k
Avg merge
2d 5h
Merged PRs (30d)
451

Description

## **Description**

During onboarding, with Bitcoin and Tron accounts enabled in production and maximum privacy settings turned off, the wallet still calls `bitcoin-mainnet.infura.io`, `tron-mainnet.infura.io`, `price.api.cx.metamask.io`, and `subscription.api.cx.metamask.io` **before** the user clicks Done. EVM RPC is already deferred until onboarding is complete; BTC/TRON default account creation, price fetches, and Shield subscription polling are not.

## **Expected behavior**

Before Done, onboarding should not talk to chain RPC or price/subscription APIs (same invariant as EVM `AccountTracker`). After the user turns off basic functionality and asset privacy toggles, those hosts should stay silent even if Bitcoin/Tron accounts are enabled.

## **Actual behavior**

The wallet-ready screen is shown correctly. Network capture during that wait still records:

- `bitcoin-mainnet.infura.io`
- `tron-mainnet.infura.io`
- `price.api.cx.metamask.io`
- `subscription.api.cx.metamask.io`

`subscription.api` was observed while toggling asset privacy off, after basic functionality was already disabled. A longer wait does not prevent the leak; it makes it more likely to be seen.

## **Screenshots/Recordings**

The UI is on the expected complete screen. The failure is unexpected network calls, not a missed click. GitHub cannot host this PNG from CLI; local copy is `issue-screenshot-onboarding-privacy-network.png` in the reporter workspace.

## **Steps to reproduce**

1. Use production-accurate remote flags (`bitcoinAccounts` and `tronAccounts` enabled).
2. Start a fresh wallet import onboarding flow.
3. On **Your wallet is ready!**, open default privacy settings.
4. Turn off basic functionality and all asset privacy toggles.
5. Go back to the complete screen (do not click Done yet).
6. Observe outbound hosts during that period.

E2E equivalent:

```bash
SELENIUM_BROWSER=chrome yarn test:e2e:single test/e2e/tests/privacy/onboarding-maximum-privacy.spec.ts
```

## **Error messages or log output**

```
AssertionError [ERR_ASSERTION]: Unexpected network calls during onboarding:
- bitcoin-mainnet.infura.io
- tron-mainnet.infura.io
- price.api.cx.metamask.io
- subscription.api.cx.metamask.io

These hosts are NOT in the duringOnboarding allowlist.
If these are expected, add them to privacy-max-allowlist-onboarding.json

4 !== 0
```

## **Technical details**

- Failed E2E: `test/e2e/tests/privacy/onboarding-maximum-privacy.spec.ts` / `should only make allowlisted network calls during and after import wallet onboarding` / assert at line 130
- Allowlist: `test/e2e/tests/privacy/privacy-max-allowlist-onboarding.json` (`duringOnboarding` has no Infura/price/subscription hosts)
- Production flags (do not override in this spec): `test/e2e/feature-flags/feature-flag-registry.ts` `bitcoinAccounts` (enabled) and `tronAccounts` (enabled), served by `test/e2e/mock-e2e.js`

Product path:

- EVM RPC waits for Done: `app/scripts/messenger-client-init/account-tracker-controller-init.ts` (`fetchingEnabled` / `isOnboarded` use `completedOnboarding`).
- Extra BTC/TRON **discovery** also waits for Done: `app/scripts/services/legacy-background-api-service.ts` (`discoverAndCreateAccounts` only if `completedOnboarding`).
- Default BTC/TRON **wallet create does not wait**: same file, `MultichainAccountService:createMultichainAccountWallet` then `MultichainAccountService:init` during vault restore, while `completedOnboarding` is still false. Bitcoin snap genesis/discovery then hits Infura (`test/e2e/mock-e2e.js` default esplora mocks).
- Price UI polling is gated on Done + currency-rate toggle: `ui/hooks/useCurrencyRatePolling.ts`. `MultichainRatesController` init is not.
- Shield polling is gated on basic functionality + signed-in + unlocked, **not** on Done: `ui/contexts/shield/shield-subscription.tsx` `shouldPoll`.

This is not a missing E2E wait or flag stub. A real user with production Bitcoin/Tron flags hits the same hosts before Done. Stubbing flags off in the spec would hide production behavior.

## **Suggested fix**

1. Defer BTC/TRON snap account create (or at least Infura) until `completedOnboarding`, matching `discoverAndCreateAccounts` in `legacy-background-api-service.ts`. Vault restore should not talk to Infura before Done.
2. Gate BTC/multichain price fetches on `completedOnboarding` and `useCurrencyRateCheck` / `useExternalServices`, matching `useCurrencyRatePolling.ts` and `assets-controller-init.ts`.
3. Add `completedOnboarding` to Shield `shouldPoll` in `shield-subscription.tsx`, and stop in-flight `/v1/subscriptions` when basic functionality is turned off.

Do not add these four hosts to `duringOnboarding` without privacy review. After Done, `bitcoin-mainnet.infura.io` / `tron-mainnet.infura.io` may belong on `untilOnboardingComplete` next to other Infura hosts. `price.api` and `subscription.api` should stay off both lists under max privacy.

## **Additional context**

- Classification: product privacy bug (async, so the E2E can flake)
- Confidence: 85%
- Residual flake: snap create / rates / Shield poll can miss the 1600ms capture window
- Do not override `feature-flag-registry.ts` defaults in `onboarding-maximum-privacy.spec.ts`
- Related: `test/e2e/tests/privacy/onboarding-token-price-call-privacy.spec.ts` (no price API before Done)
- CODEOWNERS: privacy tests `@MetaMask/extension-privacy-reviewers`; multichain accounts `@MetaMask/accounts-engineers`

Contributor guide

Open the contributing guide

Research direction

Start with test/e2e/tests/privacy/onboarding-maximum-privacy.spec.ts and its duringOnboarding allowlist in privacy-max-allowlist-onboarding.json, then read the named account, rates, and Shield initialization files. Run the listed E2E test and trace the calls observed before Done. Done means the production-flagged onboarding flow makes no non-allowlisted chain, price, or subscription requests before Done, including after privacy toggles change.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
security, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.