Skip to content

feat: add friction for malicious transactions instead of blocking#104

Merged
wantedsystem merged 8 commits into
mainfrom
feat/malicious-transaction-acknowledgement
Jun 15, 2026
Merged

feat: add friction for malicious transactions instead of blocking#104
wantedsystem merged 8 commits into
mainfrom
feat/malicious-transaction-acknowledgement

Conversation

@wantedsystem

@wantedsystem wantedsystem commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

We don't outright block users from any confirmation today, and per Blockaid the user should always be able to decide. This PR replaces the implicit block on malicious transactions with friction, mirroring EVM:

  • Malicious (with Security Alerts enabled): show the danger banner and replace Confirm with Review alert; users must acknowledge the risk and check a confirmation box before proceeding.
  • Warning: show the banner only; the button remains Confirm.
  • Benign / Security Alerts disabled: no change.

Applies to all four scanned flows: send, change-trust opt-in, change-trust opt-out, and sign-transaction.

Changes

  • Narrowed isConfirmDisabledByScan to only block while a scan is fetching.
  • Added requiresMaliciousAcknowledgement({ preferences, scan }) to drive the review flow.
  • Added shared MaliciousAcknowledgementScreen and acknowledgement event handlers.
  • Added shared ConfirmationFooter to remove button duplication across views.
  • Extracted renderConfirmationView into views/render.tsx for a single rendering path.
  • Persisted interfaceKey and acknowledgement state in the interface context.
  • Updated banner copy: "Learn more" → "See details"; "Security advice by" → "Powered by".

Implementation notes

  • No modal/overlay support in Snaps custom UI, so the acknowledgement flow is implemented as a second screen within the same interface.
  • Touches the same view files as the confirmation alert priority helper refactor; expect a small import conflict if that lands first.

Screenshots

Screenshot 2026-06-11 at 16 59 22 Screenshot 2026-06-11 at 16 59 34

@wantedsystem wantedsystem requested a review from a team as a code owner June 11, 2026 15:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the Stellar Snap confirmation UX to add friction (rather than outright blocking) for malicious transaction-scan results: the primary action becomes “Review alert”, users are routed to a second acknowledgement screen, and only then can they proceed to confirm.

Changes:

  • Introduces a shared malicious acknowledgement screen + event handlers, and routes malicious confirmations through this flow.
  • Refactors rendering to a shared renderConfirmationView and adds a shared ConfirmationFooter to centralize primary-button behavior.
  • Narrows isConfirmDisabledByScan to only disable confirmation while a scan is actively fetching, and adds requiresMaliciousAcknowledgement to drive the new UX.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/snap/src/ui/confirmation/views/render.tsx Centralizes confirmation view rendering and adds acknowledgement-screen override.
packages/snap/src/ui/confirmation/views/MaliciousAcknowledgement/MaliciousAcknowledgementScreen.tsx New acknowledgement “friction” screen UI for malicious scan results.
packages/snap/src/ui/confirmation/views/MaliciousAcknowledgement/MaliciousAcknowledgementScreen.test.tsx Unit tests for acknowledgement screen rendering and button/checkbox state.
packages/snap/src/ui/confirmation/views/MaliciousAcknowledgement/events.tsx New shared user-input handlers for review/ack/back/proceed flow.
packages/snap/src/ui/confirmation/views/MaliciousAcknowledgement/events.test.tsx Unit tests for acknowledgement event handlers and interface updates.
packages/snap/src/ui/confirmation/views/MaliciousAcknowledgement/constants.ts Shared form element names for acknowledgement flow.
packages/snap/src/ui/confirmation/views/ConfirmSignTransaction/ConfirmSignTransaction.tsx Uses shared footer and malicious acknowledgement gating.
packages/snap/src/ui/confirmation/views/ConfirmSignChangeTrustOptOut/ConfirmSignChangeTrustOptOut.tsx Uses shared footer and malicious acknowledgement gating; scan disable logic updated.
packages/snap/src/ui/confirmation/views/ConfirmSignChangeTrustOptIn/ConfirmSignChangeTrustOptIn.tsx Uses shared footer and malicious acknowledgement gating; scan disable logic updated.
packages/snap/src/ui/confirmation/views/ConfirmSendTransaction/ConfirmSendTransaction.tsx Uses shared footer and malicious acknowledgement gating; scan disable logic updated.
packages/snap/src/ui/confirmation/utils.ts Adjusts scan-based disable rules and adds requiresMaliciousAcknowledgement.
packages/snap/src/ui/confirmation/utils.test.ts Updates tests for scan-disable changes and adds tests for acknowledgement requirement logic.
packages/snap/src/ui/confirmation/controller.tsx Persists interfaceKey in context and uses shared render path.
packages/snap/src/ui/confirmation/components/index.ts Re-exports new ConfirmationFooter.
packages/snap/src/ui/confirmation/components/ConfirmationFooter.tsx New shared footer with malicious “Review alert” primary-action behavior.
packages/snap/src/ui/confirmation/components/ConfirmationFooter.test.tsx Unit tests for shared footer behavior.
packages/snap/src/ui/confirmation/api.ts Extends base confirmation context with interface key + acknowledgement screen state.
packages/snap/src/handlers/user-input/userInput.ts Registers acknowledgement event handlers alongside existing confirmation handlers.
packages/snap/snap.manifest.json Updates bundle shasum for the new build output.
packages/snap/messages.json Adds new i18n strings and updates banner copy.
packages/snap/locales/es.json Mirrors new i18n strings and updated banner copy.
packages/snap/locales/en.json Mirrors new i18n strings and updated banner copy.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/snap/src/ui/confirmation/components/ConfirmationFooter.tsx Outdated
Comment thread packages/snap/src/ui/confirmation/utils.test.ts Outdated

@stanleyyconsensys stanleyyconsensys left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

TBH, the logic has no issue

but it is a bit hard to understand by the naming of those condition check

let me know if we can update the name?

i also have a small question for onProcessClick

scan,
scanFetchStatus,
});
const shouldDisableConfirmButton = isConfirmBlocked({ scanFetchStatus });

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: can we add a comment saying sign txn does not apply local simluation?

transactionsFetchStatus?: FetchStatus;
}): boolean {
return (
isConfirmDisabledByScan({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit:

shall we update the name to
isRemoteTransactionScanLoading

isConfirmDisabledByScan({
scanFetchStatus: params.scanFetchStatus ?? FetchStatus.Initial,
}) ||
isConfirmDisabledByTransactionValidation(params.transactionsFetchStatus)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit:
should we rename to

isLocalTransactionValidateFail

scan,
scanFetchStatus,
}) || isConfirmDisabledByTransactionValidation(transactionsFetchStatus);
const shouldDisableConfirmButton = isConfirmBlocked({

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit:

should we rename to shouldDisableConfirmation

becoz isConfirmBlocked, mean if we check the confrim is blocked or not

but actually we are referring to should we do xxxxx

| undefined,
})
) {
return;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

if return means the screen will freeze ?

shall we go back instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch. Fixed it to go back to the confirmation view instead of returning a silent click

@wantedsystem wantedsystem merged commit 84b0234 into main Jun 15, 2026
10 checks passed
@wantedsystem wantedsystem deleted the feat/malicious-transaction-acknowledgement branch June 15, 2026 10:27
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.

3 participants