MetaMask / MetaMask/metamask-mobile

RemoteFeatureFlagController does not toggle disabled state on runtime Basic Functionality changes

Open
#32,090 1 comment 0 reactions 0 assignees View on GitHub
INVALID-ISSUE-TEMPLATE Sev2 size-S ta-triaged team-application-security
Dominant language
TypeScript
Stars
3k
Forks
1.7k
Avg merge
1d 14h
Merged PRs (30d)
669

Description

## What is this about?

`RemoteFeatureFlagController` only evaluates `selectBasicFunctionalityEnabled` **once, at initialization**, to set its initial `disabled` state. It does not react to runtime changes of the Basic Functionality toggle, so it never calls `enable()` / `disable()` after startup.

This is **pre-existing behaviour** (it predates the `@metamask/wallet` adoption in #31917 — the old `remote-feature-flag-controller-init.ts` had the same one-shot read) and was intentionally preserved by that migration to keep it behaviour-preserving. Filing as a follow-up.

The MetaMask Extension implementation subscribes to the toggle and flips the controller's `disabled` state accordingly. Mobile should match that.

## Current behaviour

- Initial `disabled` value is set from `selectBasicFunctionalityEnabled(store.getState())` when the controller's instance options are built:
- `app/core/Engine/wallet-init/instance-options/remote-feature-flag-controller.ts` (`disabled` field)
- Startup fetch gate in `app/core/Engine/Engine.ts` (~line 840)
- The only reactor to the toggle is the `basicFunctionalityToggle` saga (`app/store/sagas/index.ts`), which just swaps the global XHR override (`restoreXMLHttpRequest` / `overrideXMLHttpRequest`). It never calls `RemoteFeatureFlagController.enable()` / `disable()`.

### Secondary issue: the XHR override doesn't catch RFFC either

Even the XHR override path wouldn't block remote feature flag fetches: `AppConstants.BASIC_FUNCTIONALITY_BLOCK_LIST` still references the stale host `config-api.metamask.io/featureFlags`, whereas the real endpoint is `client-config.api.cx.metamask.io` (`AppConstants.FEATURE_FLAGS_API.BASE_URL`).

Net effect: toggling Basic Functionality off at runtime currently neither disables the controller nor blocks its requests.

## Expected behaviour

When the Basic Functionality toggle changes at runtime:

1. Call `RemoteFeatureFlagController.disable()` when basic functionality is turned off, and `enable()` (followed by `updateRemoteFeatureFlags()`) when it is turned back on — matching the Extension implementation.
2. Update `BASIC_FUNCTIONALITY_BLOCK_LIST` so the feature-flags host (`client-config.api.cx.metamask.io`) is actually covered, removing the stale `config-api.metamask.io/featureFlags` entry.

## References

- PR: #31917
- Reviewer comment by @FrederikBolding on the RFFC startup gate in `Engine.ts`.

Contributor guide

Open the contributing guide

Research direction

Start with app/core/Engine/wallet-init/instance-options/remote-feature-flag-controller.ts and the basicFunctionalityToggle saga in app/store/sagas/index.ts, then compare the Extension implementation referenced in the issue. Verify the startup gate in app/core/Engine/Engine.ts and the feature-flags entry in AppConstants.BASIC_FUNCTIONALITY_BLOCK_LIST. Done means runtime toggles call disable or enable/updateFeatureFlags and the current feature-flags host is covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.