1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-22 09:23:21 +01:00

Add Blockaid / PPOM Failed Request Security Alert (#20362)

* WIP blockaid: add request failed UI
- proposed to update reason value. planning to update upon update

* alphabetize

* BlockaidBannerAlert: update tkeys based on reason

* SecurityProviderBannerAlert: fix footer alignment

* BlockaidBannerAlert: rm footer w failed resultType

---------

Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com>
Co-authored-by: Jyoti Puri <jyotipuri@gmail.com>
This commit is contained in:
Ariella Vu 2023-08-14 18:38:03 +02:00 committed by GitHub
parent e9fbf8591f
commit 136ede5d4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 116 additions and 59 deletions

View File

@ -565,6 +565,9 @@
"blockaidDescriptionBlurFarming": {
"message": "If you approve this request, someone can steal your assets listed on Blur."
},
"blockaidDescriptionFailed": {
"message": "Because of an error, this request was not verified by the security provider. Proceed with caution."
},
"blockaidDescriptionMaliciousDomain": {
"message": "You're interacting with a malicious domain. If you approve this request, you might lose your assets."
},
@ -580,6 +583,9 @@
"blockaidTitleDeceptive": {
"message": "This is a deceptive request"
},
"blockaidTitleMayNotBeSafe": {
"message": "Request may not be safe"
},
"blockaidTitleSuspicious": {
"message": "This is a suspicious request"
},

View File

@ -49,8 +49,8 @@ export enum BlockaidReason {
other = 'other',
// Locally defined
notApplicable = 'NotApplicable',
failed = 'Failed',
notApplicable = 'NotApplicable',
}
export enum BlockaidResultType {

View File

@ -59,7 +59,7 @@ exports[`Security Provider Banner Alert should match snapshot 1`] = `
</details>
</div>
<p
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-2 mm-box--align-items-center mm-box--color-text-alternative"
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-3 mm-box--display-flex mm-box--align-items-center mm-box--color-text-alternative"
>
<span
class="mm-box disclosure__summary--icon mm-icon mm-icon--size-sm mm-box--margin-inline-end-1 mm-box--display-inline-block mm-box--color-primary-default"

View File

@ -21,7 +21,7 @@ exports[`Blockaid Banner Alert should render 'danger' UI when securityAlertRespo
If you approve this request, a third party known for scams might take all your assets.
</p>
<p
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-2 mm-box--align-items-center mm-box--color-text-alternative"
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-3 mm-box--display-flex mm-box--align-items-center mm-box--color-text-alternative"
>
<span
class="mm-box disclosure__summary--icon mm-icon mm-icon--size-sm mm-box--margin-inline-end-1 mm-box--display-inline-block mm-box--color-primary-default"
@ -46,6 +46,30 @@ exports[`Blockaid Banner Alert should render 'danger' UI when securityAlertRespo
</div>
`;
exports[`Blockaid Banner Alert should render 'warning' UI when securityAlertResponse.result_type is 'Failed 1`] = `
<div
class="box mm-banner-base mm-banner-alert mm-banner-alert--severity-warning box--margin-4 box--padding-3 box--padding-left-2 box--display-flex box--gap-2 box--flex-direction-row box--background-color-warning-muted box--rounded-sm"
>
<span
class="mm-box mm-icon mm-icon--size-lg mm-box--display-inline-block mm-box--color-warning-default"
style="mask-image: url('./images/icons/warning.svg');"
/>
<div>
<h5
class="mm-box mm-text mm-banner-base__title mm-text--body-lg-medium mm-box--color-text-default"
data-testid="mm-banner-base-title"
>
This is a deceptive request
</h5>
<p
class="mm-box mm-text mm-text--body-md mm-box--margin-top-2 mm-box--color-text-default"
>
If you approve this request, a third party known for scams might take all your assets.
</p>
</div>
</div>
`;
exports[`Blockaid Banner Alert should render 'warning' UI when securityAlertResponse.result_type is 'Warning 1`] = `
<div
class="box mm-banner-base mm-banner-alert mm-banner-alert--severity-warning box--margin-4 box--padding-3 box--padding-left-2 box--display-flex box--gap-2 box--flex-direction-row box--background-color-warning-muted box--rounded-sm"
@ -67,7 +91,7 @@ exports[`Blockaid Banner Alert should render 'warning' UI when securityAlertResp
If you approve this request, a third party known for scams might take all your assets.
</p>
<p
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-2 mm-box--align-items-center mm-box--color-text-alternative"
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-3 mm-box--display-flex mm-box--align-items-center mm-box--color-text-alternative"
>
<span
class="mm-box disclosure__summary--icon mm-icon mm-icon--size-sm mm-box--margin-inline-end-1 mm-box--display-inline-block mm-box--color-primary-default"
@ -152,7 +176,7 @@ exports[`Blockaid Banner Alert should render details when provided 1`] = `
</details>
</div>
<p
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-2 mm-box--align-items-center mm-box--color-text-alternative"
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-3 mm-box--display-flex mm-box--align-items-center mm-box--color-text-alternative"
>
<span
class="mm-box disclosure__summary--icon mm-icon mm-icon--size-sm mm-box--margin-inline-end-1 mm-box--display-inline-block mm-box--color-primary-default"

View File

@ -21,6 +21,8 @@ const REASON_TO_DESCRIPTION_TKEY = Object.freeze({
[BlockaidReason.blurFarming]: 'blockaidDescriptionBlurFarming',
[BlockaidReason.failed]: 'blockaidDescriptionFailed',
[BlockaidReason.seaportFarming]: 'blockaidDescriptionSeaportFarming',
[BlockaidReason.maliciousDomain]: 'blockaidDescriptionMaliciousDomain',
@ -36,8 +38,11 @@ const REASON_TO_DESCRIPTION_TKEY = Object.freeze({
[BlockaidReason.other]: 'blockaidDescriptionMightLoseAssets',
});
/** List of suspicious reason(s). Other reasons will be deemed as deceptive. */
const SUSPCIOUS_REASON = [BlockaidReason.rawSignatureFarming];
/** Reason to title translation key mapping. */
const REASON_TO_TITLE_TKEY = Object.freeze({
[BlockaidReason.failed]: 'blockaidTitleMayNotBeSafe',
[BlockaidReason.rawSignatureFarming]: 'blockaidTitleSuspicious',
});
function BlockaidBannerAlert({ securityAlertResponse }) {
const t = useContext(I18nContext);
@ -48,10 +53,7 @@ function BlockaidBannerAlert({ securityAlertResponse }) {
const { reason, result_type: resultType, features } = securityAlertResponse;
if (
resultType === BlockaidResultType.Benign ||
resultType === BlockaidResultType.Failed
) {
if (resultType === BlockaidResultType.Benign) {
return null;
}
@ -69,21 +71,20 @@ function BlockaidBannerAlert({ securityAlertResponse }) {
</Text>
);
const isFailedResultType = resultType === BlockaidResultType.Failed;
const severity =
resultType === BlockaidResultType.Malicious
? Severity.Danger
: Severity.Warning;
const title =
SUSPCIOUS_REASON.indexOf(reason) > -1
? t('blockaidTitleSuspicious')
: t('blockaidTitleDeceptive');
const title = t(REASON_TO_TITLE_TKEY[reason] || 'blockaidTitleDeceptive');
return (
<SecurityProviderBannerAlert
description={description}
details={details}
provider={SecurityProvider.Blockaid}
provider={isFailedResultType ? null : SecurityProvider.Blockaid}
severity={severity}
title={title}
/>

View File

@ -40,7 +40,7 @@ describe('Blockaid Banner Alert', () => {
expect(container.querySelector('.mm-banner-alert')).toBeNull();
});
it(`should not render when securityAlertResponse.result_type is '${BlockaidResultType.Failed}'`, () => {
it(`should render '${Severity.Warning}' UI when securityAlertResponse.result_type is '${BlockaidResultType.Failed}`, () => {
const { container } = renderWithLocalization(
<BlockaidBannerAlert
securityAlertResponse={{
@ -49,8 +49,24 @@ describe('Blockaid Banner Alert', () => {
}}
/>,
);
const warningBannerAlert = container.querySelector(
'.mm-banner-alert--severity-warning',
);
expect(container.querySelector('.mm-banner-alert')).toBeNull();
expect(warningBannerAlert).toBeInTheDocument();
expect(warningBannerAlert).toMatchSnapshot();
});
it(`should render '${Severity.Warning}' UI when securityAlertResponse.result_type is '${BlockaidResultType.Warning}`, () => {
const { container } = renderWithLocalization(
<BlockaidBannerAlert securityAlertResponse={mockSecurityAlertResponse} />,
);
const warningBannerAlert = container.querySelector(
'.mm-banner-alert--severity-warning',
);
expect(warningBannerAlert).toBeInTheDocument();
expect(warningBannerAlert).toMatchSnapshot();
});
it(`should render '${Severity.Danger}' UI when securityAlertResponse.result_type is '${BlockaidResultType.Malicious}`, () => {
@ -70,18 +86,6 @@ describe('Blockaid Banner Alert', () => {
expect(dangerBannerAlert).toMatchSnapshot();
});
it(`should render '${Severity.Warning}' UI when securityAlertResponse.result_type is '${BlockaidResultType.Warning}`, () => {
const { container } = renderWithLocalization(
<BlockaidBannerAlert securityAlertResponse={mockSecurityAlertResponse} />,
);
const warningBannerAlert = container.querySelector(
'.mm-banner-alert--severity-warning',
);
expect(warningBannerAlert).toBeInTheDocument();
expect(warningBannerAlert).toMatchSnapshot();
});
it('should render title, "This is a deceptive request"', () => {
const { getByText } = renderWithLocalization(
<BlockaidBannerAlert securityAlertResponse={mockSecurityAlertResponse} />,
@ -90,7 +94,20 @@ describe('Blockaid Banner Alert', () => {
expect(getByText('This is a deceptive request')).toBeInTheDocument();
});
it('should render title, "This is a suspicious request", when the reason is "raw_signature_farming"', () => {
it(`should render title, "This is a suspicious request", when the reason is "${BlockaidReason.failed}"`, () => {
const { getByText } = renderWithLocalization(
<BlockaidBannerAlert
securityAlertResponse={{
...mockSecurityAlertResponse,
reason: BlockaidReason.failed,
}}
/>,
);
expect(getByText('Request may not be safe')).toBeInTheDocument();
});
it(`should render title, "This is a suspicious request", when the reason is "${BlockaidReason.rawSignatureFarming}"`, () => {
const { getByText } = renderWithLocalization(
<BlockaidBannerAlert
securityAlertResponse={{
@ -131,6 +148,8 @@ describe('Blockaid Banner Alert', () => {
'If you approve this request, a third party known for scams might take all your assets.',
[BlockaidReason.blurFarming]:
'If you approve this request, someone can steal your assets listed on Blur.',
[BlockaidReason.failed]:
'Because of an error, this request was not verified by the security provider. Proceed with caution.',
[BlockaidReason.maliciousDomain]:
"You're interacting with a malicious domain. If you approve this request, you might lose your assets.",
[BlockaidReason.other]:

View File

@ -15,6 +15,7 @@ import { I18nContext } from '../../../contexts/i18n';
import {
AlignItems,
Color,
Display,
IconColor,
Severity,
Size,
@ -45,30 +46,33 @@ function SecurityProviderBannerAlert({
</Disclosure>
)}
<Text
marginTop={2}
alignItems={AlignItems.center}
color={Color.textAlternative}
variant={TextVariant.bodySm}
>
<Icon
className="disclosure__summary--icon"
color={IconColor.primaryDefault}
name={IconName.SecurityTick}
size={IconSize.Sm}
marginInlineEnd={1}
/>
{t('securityProviderAdviceBy', [
<ButtonLink
key={`security-provider-button-link-${provider}`}
size={Size.inherit}
href={SECURITY_PROVIDER_CONFIG[provider].url}
externalLink
>
{t(SECURITY_PROVIDER_CONFIG[provider].tKeyName)}
</ButtonLink>,
])}
</Text>
{provider && (
<Text
marginTop={3}
display={Display.Flex}
alignItems={AlignItems.center}
color={Color.textAlternative}
variant={TextVariant.bodySm}
>
<Icon
className="disclosure__summary--icon"
color={IconColor.primaryDefault}
name={IconName.SecurityTick}
size={IconSize.Sm}
marginInlineEnd={1}
/>
{t('securityProviderAdviceBy', [
<ButtonLink
key={`security-provider-button-link-${provider}`}
size={Size.inherit}
href={SECURITY_PROVIDER_CONFIG[provider].url}
externalLink
>
{t(SECURITY_PROVIDER_CONFIG[provider].tKeyName)}
</ButtonLink>,
])}
</Text>
)}
</BannerAlert>
);
}
@ -78,9 +82,6 @@ SecurityProviderBannerAlert.propTypes = {
description: PropTypes.oneOfType([PropTypes.string, PropTypes.element])
.isRequired,
/** Name of the security provider */
provider: PropTypes.oneOfType(Object.values(SecurityProvider)).isRequired,
/** Severity level */
severity: PropTypes.oneOfType([Severity.Danger, Severity.Warning]).isRequired,
@ -93,6 +94,9 @@ SecurityProviderBannerAlert.propTypes = {
/** Additional details to be displayed under the description */
details: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
/** Name of the security provider */
provider: PropTypes.oneOfType(Object.values(SecurityProvider)),
};
export default SecurityProviderBannerAlert;

View File

@ -53,7 +53,10 @@ export default {
control: {
type: 'select',
},
options: [Object.values(SecurityProvider)],
options: ['none', ...Object.values(SecurityProvider)],
mapping: {
none: null,
},
},
severity: {
control: {