Skip to content

chore: add blockaid filter logic for spl tokens#7923

Open
sahar-fehri wants to merge 6 commits intomainfrom
fix/add-blockaid-filter-for-spl-tokens
Open

chore: add blockaid filter logic for spl tokens#7923
sahar-fehri wants to merge 6 commits intomainfrom
fix/add-blockaid-filter-for-spl-tokens

Conversation

@sahar-fehri
Copy link
Contributor

@sahar-fehri sahar-fehri commented Feb 12, 2026

Explanation

Adds Blockaid token security scanning to MultichainAssetsController to filter out spam, malicious, and warning SPL tokens before they are stored in state.
(Related: https://consensys.slack.com/archives/C04J5RRJYTE/p1770216744026999)

  • New #filterBlockaidSpamTokens method — Groups incoming token assets by chain, calls the Blockaid bulk scan endpoint (/token/scan-bulk), and removes any token flagged as Spam, Malicious, or Warning. Native assets (slip44) are passed through without scanning.

  • Fail-open behavior — If the Blockaid API request fails or a token has no result in the response, the token is kept (not filtered out).

  • Filtering is applied in two flows:
    accountAssetListUpdated — newly added tokens are scanned before being persisted.
    accountAdded — the full asset list retrieved from the snap is scanned before initial storage.

References

Checklist

  • I've updated the test suite for new or updated code as appropriate
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

Note

Medium Risk
Touches asset-detection state updates and introduces a new external API dependency/timeout path; while it fails open, scan results can change which tokens get persisted and displayed.

Overview
Adds Blockaid token security filtering to automatic multichain asset detection. MultichainAssetsController now bulk-scans newly detected CAIP-19 assets with assetNamespace token (e.g. SPL tokens) via https://security-alerts.api.cx.metamask.io/token/scan-bulk and only persists tokens rated Benign, leaving native assets (e.g. slip44) unscanned.

Filtering is applied when a non-EVM account is added and when handling AccountsController:accountAssetListUpdated additions, using timeoutFetch with a 10s timeout and fail-open behavior (API errors/timeouts/missing results keep tokens). Tests and changelog were updated to cover spam/malicious/warning cases, timeouts/errors, and ensuring curated addAssets remains unfiltered.

Written by Cursor Bugbot for commit 0d08f8b. This will update automatically on new commits. Configure here.

@sahar-fehri
Copy link
Contributor Author

@metamaskbot publish-preview

@github-actions
Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/account-tree-controller": "4.1.1-preview-1a74d12",
  "@metamask-previews/accounts-controller": "36.0.0-preview-1a74d12",
  "@metamask-previews/address-book-controller": "7.0.1-preview-1a74d12",
  "@metamask-previews/ai-controllers": "0.0.0-preview-1a74d12",
  "@metamask-previews/analytics-controller": "1.0.0-preview-1a74d12",
  "@metamask-previews/analytics-data-regulation-controller": "0.0.0-preview-1a74d12",
  "@metamask-previews/announcement-controller": "8.0.0-preview-1a74d12",
  "@metamask-previews/app-metadata-controller": "2.0.0-preview-1a74d12",
  "@metamask-previews/approval-controller": "8.0.0-preview-1a74d12",
  "@metamask-previews/assets-controller": "1.0.0-preview-1a74d12",
  "@metamask-previews/assets-controllers": "99.3.2-preview-1a74d12",
  "@metamask-previews/base-controller": "9.0.0-preview-1a74d12",
  "@metamask-previews/bridge-controller": "66.1.1-preview-1a74d12",
  "@metamask-previews/bridge-status-controller": "66.0.2-preview-1a74d12",
  "@metamask-previews/build-utils": "3.0.4-preview-1a74d12",
  "@metamask-previews/chain-agnostic-permission": "1.4.0-preview-1a74d12",
  "@metamask-previews/claims-controller": "0.4.2-preview-1a74d12",
  "@metamask-previews/composable-controller": "12.0.0-preview-1a74d12",
  "@metamask-previews/connectivity-controller": "0.1.0-preview-1a74d12",
  "@metamask-previews/controller-utils": "11.18.0-preview-1a74d12",
  "@metamask-previews/core-backend": "5.1.1-preview-1a74d12",
  "@metamask-previews/delegation-controller": "2.0.1-preview-1a74d12",
  "@metamask-previews/earn-controller": "11.1.0-preview-1a74d12",
  "@metamask-previews/eip-5792-middleware": "2.1.0-preview-1a74d12",
  "@metamask-previews/eip-7702-internal-rpc-middleware": "0.1.0-preview-1a74d12",
  "@metamask-previews/eip1193-permission-middleware": "1.0.3-preview-1a74d12",
  "@metamask-previews/ens-controller": "19.0.2-preview-1a74d12",
  "@metamask-previews/error-reporting-service": "3.0.1-preview-1a74d12",
  "@metamask-previews/eth-block-tracker": "15.0.1-preview-1a74d12",
  "@metamask-previews/eth-json-rpc-middleware": "23.1.0-preview-1a74d12",
  "@metamask-previews/eth-json-rpc-provider": "6.0.0-preview-1a74d12",
  "@metamask-previews/foundryup": "1.0.1-preview-1a74d12",
  "@metamask-previews/gas-fee-controller": "26.0.2-preview-1a74d12",
  "@metamask-previews/gator-permissions-controller": "1.1.2-preview-1a74d12",
  "@metamask-previews/json-rpc-engine": "10.2.2-preview-1a74d12",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.8-preview-1a74d12",
  "@metamask-previews/keyring-controller": "25.1.0-preview-1a74d12",
  "@metamask-previews/logging-controller": "7.0.1-preview-1a74d12",
  "@metamask-previews/message-manager": "14.1.0-preview-1a74d12",
  "@metamask-previews/messenger": "0.3.0-preview-1a74d12",
  "@metamask-previews/multichain-account-service": "7.0.0-preview-1a74d12",
  "@metamask-previews/multichain-api-middleware": "1.2.6-preview-1a74d12",
  "@metamask-previews/multichain-network-controller": "3.0.3-preview-1a74d12",
  "@metamask-previews/multichain-transactions-controller": "7.0.1-preview-1a74d12",
  "@metamask-previews/name-controller": "9.0.0-preview-1a74d12",
  "@metamask-previews/network-controller": "29.0.0-preview-1a74d12",
  "@metamask-previews/network-enablement-controller": "4.1.0-preview-1a74d12",
  "@metamask-previews/notification-services-controller": "22.0.0-preview-1a74d12",
  "@metamask-previews/permission-controller": "12.2.0-preview-1a74d12",
  "@metamask-previews/permission-log-controller": "5.0.0-preview-1a74d12",
  "@metamask-previews/perps-controller": "0.0.0-preview-1a74d12",
  "@metamask-previews/phishing-controller": "16.2.0-preview-1a74d12",
  "@metamask-previews/polling-controller": "16.0.2-preview-1a74d12",
  "@metamask-previews/preferences-controller": "22.1.0-preview-1a74d12",
  "@metamask-previews/profile-metrics-controller": "3.0.1-preview-1a74d12",
  "@metamask-previews/profile-sync-controller": "27.1.0-preview-1a74d12",
  "@metamask-previews/ramps-controller": "8.0.0-preview-1a74d12",
  "@metamask-previews/rate-limit-controller": "7.0.0-preview-1a74d12",
  "@metamask-previews/remote-feature-flag-controller": "4.0.0-preview-1a74d12",
  "@metamask-previews/sample-controllers": "4.0.2-preview-1a74d12",
  "@metamask-previews/seedless-onboarding-controller": "8.0.0-preview-1a74d12",
  "@metamask-previews/selected-network-controller": "26.0.2-preview-1a74d12",
  "@metamask-previews/shield-controller": "5.0.1-preview-1a74d12",
  "@metamask-previews/signature-controller": "39.0.2-preview-1a74d12",
  "@metamask-previews/storage-service": "1.0.0-preview-1a74d12",
  "@metamask-previews/subscription-controller": "6.0.0-preview-1a74d12",
  "@metamask-previews/transaction-controller": "62.17.0-preview-1a74d12",
  "@metamask-previews/transaction-pay-controller": "14.0.0-preview-1a74d12",
  "@metamask-previews/user-operation-controller": "41.0.2-preview-1a74d12"
}

@sahar-fehri sahar-fehri marked this pull request as ready for review February 13, 2026 09:07
@sahar-fehri sahar-fehri requested review from a team as code owners February 13, 2026 09:07
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Comment on lines 45 to 47
const mockHandleFetch = ControllerUtils.handleFetch as jest.MockedFunction<
typeof ControllerUtils.handleFetch
>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - we can use jest.mocked and avoid type assertions.

const mockHandleFetch = jest.mocked(ControllerUtils.handleFetch)

@sahar-fehri
Copy link
Contributor Author

@metamaskbot publish-preview

@github-actions
Copy link
Contributor

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/account-tree-controller": "4.1.1-preview-0d08f8bdc",
  "@metamask-previews/accounts-controller": "36.0.0-preview-0d08f8bdc",
  "@metamask-previews/address-book-controller": "7.0.1-preview-0d08f8bdc",
  "@metamask-previews/ai-controllers": "0.0.0-preview-0d08f8bdc",
  "@metamask-previews/analytics-controller": "1.0.0-preview-0d08f8bdc",
  "@metamask-previews/analytics-data-regulation-controller": "0.0.0-preview-0d08f8bdc",
  "@metamask-previews/announcement-controller": "8.0.0-preview-0d08f8bdc",
  "@metamask-previews/app-metadata-controller": "2.0.0-preview-0d08f8bdc",
  "@metamask-previews/approval-controller": "8.0.0-preview-0d08f8bdc",
  "@metamask-previews/assets-controller": "1.0.0-preview-0d08f8bdc",
  "@metamask-previews/assets-controllers": "99.3.2-preview-0d08f8bdc",
  "@metamask-previews/base-controller": "9.0.0-preview-0d08f8bdc",
  "@metamask-previews/bridge-controller": "66.1.1-preview-0d08f8bdc",
  "@metamask-previews/bridge-status-controller": "66.0.2-preview-0d08f8bdc",
  "@metamask-previews/build-utils": "3.0.4-preview-0d08f8bdc",
  "@metamask-previews/chain-agnostic-permission": "1.4.0-preview-0d08f8bdc",
  "@metamask-previews/claims-controller": "0.4.2-preview-0d08f8bdc",
  "@metamask-previews/composable-controller": "12.0.0-preview-0d08f8bdc",
  "@metamask-previews/connectivity-controller": "0.1.0-preview-0d08f8bdc",
  "@metamask-previews/controller-utils": "11.18.0-preview-0d08f8bdc",
  "@metamask-previews/core-backend": "5.1.1-preview-0d08f8bdc",
  "@metamask-previews/delegation-controller": "2.0.1-preview-0d08f8bdc",
  "@metamask-previews/earn-controller": "11.1.0-preview-0d08f8bdc",
  "@metamask-previews/eip-5792-middleware": "2.1.0-preview-0d08f8bdc",
  "@metamask-previews/eip-7702-internal-rpc-middleware": "0.1.0-preview-0d08f8bdc",
  "@metamask-previews/eip1193-permission-middleware": "1.0.3-preview-0d08f8bdc",
  "@metamask-previews/ens-controller": "19.0.2-preview-0d08f8bdc",
  "@metamask-previews/error-reporting-service": "3.0.1-preview-0d08f8bdc",
  "@metamask-previews/eth-block-tracker": "15.0.1-preview-0d08f8bdc",
  "@metamask-previews/eth-json-rpc-middleware": "23.1.0-preview-0d08f8bdc",
  "@metamask-previews/eth-json-rpc-provider": "6.0.0-preview-0d08f8bdc",
  "@metamask-previews/foundryup": "1.0.1-preview-0d08f8bdc",
  "@metamask-previews/gas-fee-controller": "26.0.2-preview-0d08f8bdc",
  "@metamask-previews/gator-permissions-controller": "1.1.2-preview-0d08f8bdc",
  "@metamask-previews/json-rpc-engine": "10.2.2-preview-0d08f8bdc",
  "@metamask-previews/json-rpc-middleware-stream": "8.0.8-preview-0d08f8bdc",
  "@metamask-previews/keyring-controller": "25.1.0-preview-0d08f8bdc",
  "@metamask-previews/logging-controller": "7.0.1-preview-0d08f8bdc",
  "@metamask-previews/message-manager": "14.1.0-preview-0d08f8bdc",
  "@metamask-previews/messenger": "0.3.0-preview-0d08f8bdc",
  "@metamask-previews/multichain-account-service": "7.0.0-preview-0d08f8bdc",
  "@metamask-previews/multichain-api-middleware": "1.2.6-preview-0d08f8bdc",
  "@metamask-previews/multichain-network-controller": "3.0.3-preview-0d08f8bdc",
  "@metamask-previews/multichain-transactions-controller": "7.0.1-preview-0d08f8bdc",
  "@metamask-previews/name-controller": "9.0.0-preview-0d08f8bdc",
  "@metamask-previews/network-controller": "29.0.0-preview-0d08f8bdc",
  "@metamask-previews/network-enablement-controller": "4.1.0-preview-0d08f8bdc",
  "@metamask-previews/notification-services-controller": "22.0.0-preview-0d08f8bdc",
  "@metamask-previews/permission-controller": "12.2.0-preview-0d08f8bdc",
  "@metamask-previews/permission-log-controller": "5.0.0-preview-0d08f8bdc",
  "@metamask-previews/perps-controller": "0.0.0-preview-0d08f8bdc",
  "@metamask-previews/phishing-controller": "16.2.0-preview-0d08f8bdc",
  "@metamask-previews/polling-controller": "16.0.2-preview-0d08f8bdc",
  "@metamask-previews/preferences-controller": "22.1.0-preview-0d08f8bdc",
  "@metamask-previews/profile-metrics-controller": "3.0.1-preview-0d08f8bdc",
  "@metamask-previews/profile-sync-controller": "27.1.0-preview-0d08f8bdc",
  "@metamask-previews/ramps-controller": "8.0.0-preview-0d08f8bdc",
  "@metamask-previews/rate-limit-controller": "7.0.0-preview-0d08f8bdc",
  "@metamask-previews/remote-feature-flag-controller": "4.0.0-preview-0d08f8bdc",
  "@metamask-previews/sample-controllers": "4.0.2-preview-0d08f8bdc",
  "@metamask-previews/seedless-onboarding-controller": "8.0.0-preview-0d08f8bdc",
  "@metamask-previews/selected-network-controller": "26.0.2-preview-0d08f8bdc",
  "@metamask-previews/shield-controller": "5.0.1-preview-0d08f8bdc",
  "@metamask-previews/signature-controller": "39.0.2-preview-0d08f8bdc",
  "@metamask-previews/storage-service": "1.0.0-preview-0d08f8bdc",
  "@metamask-previews/subscription-controller": "6.0.0-preview-0d08f8bdc",
  "@metamask-previews/transaction-controller": "62.17.0-preview-0d08f8bdc",
  "@metamask-previews/transaction-pay-controller": "15.0.0-preview-0d08f8bdc",
  "@metamask-previews/user-operation-controller": "41.0.2-preview-0d08f8bdc"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants