Skip to content

feat: add address poisoning detection to PhishingController#8171

Open
AugmentedMode wants to merge 7 commits intomainfrom
feat/address-poisoning-detection
Open

feat: add address poisoning detection to PhishingController#8171
AugmentedMode wants to merge 7 commits intomainfrom
feat/address-poisoning-detection

Conversation

@AugmentedMode
Copy link
Contributor

@AugmentedMode AugmentedMode commented Mar 10, 2026

Explanation

This PR adds address poisoning detection to @metamask/phishing-controller by:

  • Introducing a findSimilarAddresses utility that compares a candidate address against known recipients using prefix/suffix matching heuristics
  • Exposing a new PhishingController:checkAddressPoisoning messenger action that clients can call to check if a recipient address looks like a poisoning attempt
  • Hydrating and maintaining a set of known recipient addresses from:
    • Confirmed transactions via TransactionController state
    • Address book entries via AddressBookController state
  • Subscribing to state changes on both controllers to keep the known recipients set up to date
  • Returning match metadata (prefix/suffix match lengths, poisoning score, diff indices) so consumers can make informed decisions about how to warn users

References

  • Related to address poisoning attack vector (learn more)

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
Adds new cross-controller subscriptions and state hydration paths (transactions + address book), which can affect runtime behavior and messaging contracts if states/events differ across environments.

Overview
Adds address-poisoning detection to PhishingController via a new findSimilarAddresses utility and PhishingController:checkAddressPoisoning action that returns similarity metadata (prefix/suffix match lengths, score, diff indices).

The controller now hydrates and maintains a set of known recipient addresses from confirmed TransactionController recipients and AddressBookController entries, subscribing to both controllers’ stateChange events to keep this set updated; errors updating known recipients are logged but do not block existing token scanning. This introduces new exported types (SimilarAddressMatch, SimilarityOptions), adds @metamask/address-book-controller as a dependency, and expands tests accordingly.

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

@AugmentedMode AugmentedMode requested review from a team as code owners March 10, 2026 20:27
@AugmentedMode AugmentedMode changed the title Feat/address poisoning detection feat: add address poisoning detection to PhishingController Mar 11, 2026
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 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

this.#transactionRecipients.add(address);
}
this.#rebuildKnownRecipients();
}
Copy link

Choose a reason for hiding this comment

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

Premature clear causes recipient data loss on error

Medium Severity

#setKnownRecipientsFromTransactionState calls this.#transactionRecipients.clear() before iterating state.transactions. If #getConfirmedTransactionRecipients throws (e.g. state.transactions is undefined), the set is left empty and #rebuildKnownRecipients is never called. This leaves #transactionRecipients empty while #knownRecipients retains stale entries. On the next successful #rebuildKnownRecipients call (triggered by an address book update), those stale transaction recipients are permanently lost. The same pattern exists in #setKnownRecipientsFromAddressBookState.

Additional Locations (1)
Fix in Cursor Fix in Web


#onAddressBookControllerStateChange(state: AddressBookControllerState): void {
this.#setKnownRecipientsFromAddressBookState(state);
}
Copy link

Choose a reason for hiding this comment

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

Address book handler lacks error handling unlike transaction handler

Medium Severity

#onAddressBookControllerStateChange directly calls #setKnownRecipientsFromAddressBookState without a try-catch, unlike #onTransactionControllerStateChange which wraps its recipient update in a nested try-catch. If the address book state is malformed, the unhandled error propagates into the messenger's event dispatch, potentially disrupting other event listeners or causing an unhandled exception.

Fix in Cursor Fix in Web

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.

1 participant