Skip to content

feat: integrate PhishingDataService and add migration 224 - #45643

Draft
0xOhm wants to merge 4 commits into
mainfrom
feat/psafe-593-phishing-data-service-integration
Draft

0xOhm wants to merge 4 commits into
mainfrom
feat/psafe-593-phishing-data-service-integration

Conversation

@0xOhm

@0xOhm 0xOhm commented Aug 20, 2026

Copy link
Copy Markdown

Description

Integrates the new PhishingDataService from MetaMask/core#9914 (PSAFE-593) alongside PhishingController, and adds migration 224 to drop the controller's legacy scan caches now owned by the service.

CHANGELOG entry: null

Changes

  • New phishing-data-service-init + messenger wiring in messenger-client-init
  • PhishingController messenger updated for the service-backed data flow
  • shared/constants/data-services.ts registers PhishingDataService alongside the money-account services
  • Migration 224 removes the three legacy scan caches from PhishingController state (surgical + idempotent, covered by fixture tests)

Dependency note — draft until core publishes

This PR intentionally does not bump @metamask/phishing-controller yet. main currently ships 17.4.0, which does not contain PhishingDataService; once MetaMask/core#9914 merges it will publish as a major (18.0.0) because of its breaking changes, and the bump lands here then. Verification below ran against the locally built package via file: resolutions.

Also worth noting for the bump: core's phishing-controller now requires @metamask/storage-service@^1.0.2 (this repo declares ^1.0.0, so the resolution needs to land at ≥ 1.0.2) and @tanstack/query-core@^5.62.16.

Migration numbering

Originally authored as migration 222. main has since shipped 222 (delete persisted EnsController state) and 223 (move StorageService data to IndexedDB), so this is now 224.

Migration 223 is compatible with this work: it relocates the backing store behind StorageService, and PhishingDataService persistence goes through the StorageService:getItem/setItem/removeItem messenger actions, so the change is transparent to it.

Verification

  • Migration 224 unit tests + migrations.test.js + lib/migrator/index.test.js — 13 passing
  • 10 new integration tests + migrations meta-test, full yarn lint:tsc clean against the new package
  • E2E on real Chrome (webpack test build): all 3 phishing-controller specs, 20/20 passing — blocklist warning page, iframe variants, C2 websocket blocking, path-based blocklists, redirects, v1 API request-contract spec
  • Manual checks remaining: upgrade-in-place on a real profile, SW persistence in real Chrome, outage degradation (tracked in the PSAFE-593 verification report)

Re-verification pending

The integration/e2e results above predate the merge of main (252 commits) and the core dependency bump. They need re-running against the published 18.0.0 once core releases.

🤖 Generated with Claude Code

Wire the new PhishingDataService messenger/init alongside
PhishingController and add migration 222 to drop the controller's
legacy scan caches now owned by the service.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 20, 2026

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-product-safety Push issues to Product Safety team label Aug 20, 2026
0xOhm and others added 2 commits August 26, 2026 12:13
…tion

Resolve the migration-number collision and data-service registry conflict.

- Renumber our PhishingController cache-removal migration from 222 to 224.
  Main shipped 222 (delete persisted EnsController state) and 223 (move
  StorageService data to IndexedDB) in the meantime, so 222 was taken.
  `oldVersion` in the test moves from 221 to 223 to match.
- Register 223 and 224 in `migrations/index.js`.
- `DATA_SERVICES` keeps main's `MoneyAccountBalanceService` and
  `MoneyAccountApiDataService` plus its `createUIQueryClient` comment, and
  adds `PhishingDataService`.

Still pending, tracked separately: `@metamask/phishing-controller` is not
bumped yet, so this cannot pass typecheck against the published package
until MetaMask/core#9914 merges and releases.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Migrations at or above MIGRATION_V2_START_VERSION (186) must mutate
`versionedData` in place, record touched controllers in `changedControllers`,
and return nothing. Migration 224 was written in the pre-186 style: it
deep-cloned and returned new state.

At runtime the migrator would have thrown "migration returned value when none
expected", emitted an error, and broken out of the migration loop -- leaving
the legacy scan caches in place and stopping every later migration. It also
never reported `PhishingController` as changed, so the deletion would not
have been persisted under split state.

The unit test missed this because it called `migrate()` directly rather than
through the Migrator. `app/scripts/lib/migrator/index.test.js`'s "should match
the last version in live migrations" catches it, and now passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@0xOhm 0xOhm changed the title feat: integrate PhishingDataService and add migration 222 feat: integrate PhishingDataService and add migration 224 Aug 26, 2026
@metamask-ci metamask-ci Bot added the INVALID-PR-TEMPLATE PR's body doesn't match template label Aug 26, 2026
@metamask-ci

metamask-ci Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

✨ Files requiring CODEOWNER review ✨

🫰 @MetaMask/core-platform (1 files, +2 -0)
  • 📁 app/
    • 📁 scripts/
      • 📄 metamask-controller.js +2 -0

👨‍🔧 @MetaMask/extension-platform (1 files, +2 -0)
  • 📁 app/
    • 📁 scripts/
      • 📄 metamask-controller.js +2 -0

@metamask-ci

metamask-ci Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor
Builds ready [5739141]
⚡ Performance Benchmarks (Total: 🟢 16 pass · 🟡 0 warn · 🔴 0 fail)

Baseline (latest main): 171ed20 | Date: 7/28/2026 | Pipeline: 32994211517 | Baseline logs

Interaction Benchmarks · Samples: 5
Benchmarkchrome-webpackfirefox-webpack
loadNewAccount
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
confirmTx
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
bridgeUserActions
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
User Journey Benchmarks · Samples: 5 · mock API

⚠️ Missing data: chrome/webpack/userJourneyAssets, chrome/webpack/userJourneyTransactions

Benchmarkchrome-webpackfirefox-webpack
onboardingImportWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
onboardingNewWallet
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
importSrpHome
[Sentry log · main/release]
🟢 [CI log]🟢 [CI log]
assetDetails
[Sentry log · main/release]
🟢 [CI log]
solanaAssetDetails
[Sentry log · main/release]
🟢 [CI log]
sendTransactions
[Sentry log · main/release]
🟢 [CI log]
swap
[Sentry log · main/release]
🟢 [CI log]
Dapp Page Load Benchmarks · Samples: 100

⚠️ Missing data: chrome/webpack/pageLoadBenchmark

✅ No regressions detected

Bundle size diffs [🚨 Warning! Bundle size has increased!]
  • background: 2.89 KiB (0.02%)
  • ui: 14.98 KiB (0.08%)
  • common: 0 Bytes (0%)
  • other: 0 Bytes (0%)
  • contentScripts: 232 Bytes (0.01%)
  • zip: 6.12 KiB (0.03%)

@adonesky1

Copy link
Copy Markdown
Contributor

The UI read path doesn't look migrated here. Migration 224 deletes urlScanCache, tokenScanCache, and addressScanCache, and the refactored controller no longer holds them, but the selectors still read them off state.metamask:

With the key gone, useOriginTrustSignals returns TrustSignalDisplayState.Unknown for every origin, which blanks the connect-page pill, the ConnectionTrustSignalGate malicious modal, and the origin alerts on confirmations.

Mobile's counterpart already handles this. metamask-mobile#35057 drops the selector and reads the query cache instead:

const { data: scanResult } = useQuery<PhishingDetectionScanResult>({
  queryKey: ['PhishingDataService:scanUrl', hostname ?? ''],
  enabled: Boolean(hostname),
});

(useOriginTrustSignals.ts#L56-L58). @metamask/react-data-query is already in the extension's package.json at ^0.2.2.

Worth flagging that this is easy to miss in manual testing: RecommendedAction.None and a cache miss both map to Unknown, so on a benign dapp the UI is identical before and after. It only shows up on a verified, warn, or block origin.

Is the UI migration planned as a separate PR?

@0xOhm

0xOhm commented Aug 26, 2026

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

…ache

Migration 224 deletes urlScanCache, tokenScanCache and addressScanCache from
PhishingController state, but the UI still read the first two off
state.metamask, so every origin and token resolved to Unknown.

Point the trust signal hooks at the PhishingDataService query cache instead,
matching metamask-mobile#35057:

- useOriginTrustSignals now uses `useQuery` on
  ['PhishingDataService:scanUrl', <scan url param>]. The key uses
  getPhishingDetectionScanUrlParam rather than the bare hostname, so it is
  the same entry PhishingController.scanUrl primes from the background and
  it keeps working for path-based gateway hosts.
- useTokenTrustSignalsForAddresses now uses `useQueries` on
  ['PhishingDataService:scanToken', chain, token], resolving the chain name
  and preserving address case on non-EVM chains, as the service does.

Drop the selectors that read the removed state: getUrlScanCacheResult,
getTokenScanCache and getTokenScanResultsForAddresses, plus
ui/selectors/token-scan.ts, which had no production consumers.

selectNonEvmTransactionsForActivity also read tokenScanCache to hide
transactions carrying malicious tokens. Its cache keys never matched what
MultichainAssetsController and TokenDataSource wrote (they call
bulkScanTokens with chainId: chain.namespace, so entries were keyed
`solana:<CasePreservedMint>`, while the selector built
`solana:5eykt4un...:<lowercased mint>`), so the filter was already inert
before this change. Remove the dead read; rewiring it against the query
cache with correct keys is a follow-up.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

INVALID-PR-TEMPLATE PR's body doesn't match template size-XL team-product-safety Push issues to Product Safety team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants