diff --git a/ui/components/app/signature-request-original/signature-request-original.component.js b/ui/components/app/signature-request-original/signature-request-original.component.js
index 1260c3d44..570d5821a 100644
--- a/ui/components/app/signature-request-original/signature-request-original.component.js
+++ b/ui/components/app/signature-request-original/signature-request-original.component.js
@@ -5,7 +5,7 @@ import { ObjectInspector } from 'react-inspector';
import LedgerInstructionField from '../ledger-instruction-field';
import { MESSAGE_TYPE } from '../../../../shared/constants/app';
-import { getURLHostName } from '../../../helpers/utils/util';
+import { getURLHostName, sanitizeString } from '../../../helpers/utils/util';
import { stripHexPrefix } from '../../../../shared/modules/hexstring-utils';
import Button from '../../ui/button';
import SiteOrigin from '../../ui/site-origin';
@@ -177,8 +177,12 @@ export default class SignatureRequestOriginal extends Component {
className="request-signature__row"
key={`request-signature-row-${index}`}
>
-
{`${name}:`}
- {value}
+
+ {sanitizeString(`${name}:`)}
+
+
+ {sanitizeString(value)}
+
);
})}
diff --git a/ui/components/app/signature-request-original/signature-request-original.test.js b/ui/components/app/signature-request-original/signature-request-original.test.js
index 0b5b75834..5f7e04c93 100644
--- a/ui/components/app/signature-request-original/signature-request-original.test.js
+++ b/ui/components/app/signature-request-original/signature-request-original.test.js
@@ -52,14 +52,17 @@ const props = {
},
};
-const render = () => {
+const render = (txData = props.txData) => {
const store = configureStore({
metamask: {
...mockState.metamask,
},
});
- return renderWithProvider(, store);
+ return renderWithProvider(
+ ,
+ store,
+ );
};
describe('SignatureRequestOriginal', () => {
@@ -92,4 +95,24 @@ describe('SignatureRequestOriginal', () => {
fireEvent.click(signButton);
expect(screen.getByText('Your funds may be at risk')).toBeInTheDocument();
});
+
+ it('should escape RTL character in label or value', () => {
+ const txData = {
+ msgParams: {
+ from: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
+ data: [
+ {
+ type: 'string',
+ name: 'Message \u202E test',
+ value: 'Hi, \u202E Alice!',
+ },
+ ],
+ origin: 'https://happydapp.website/governance?futarchy=true',
+ },
+ type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA,
+ };
+ const { getByText } = render(txData);
+ expect(getByText('Message \\u202E test:')).toBeInTheDocument();
+ expect(getByText('Hi, \\u202E Alice!')).toBeInTheDocument();
+ });
});
diff --git a/ui/components/app/signature-request/signature-request-data/signature-request-data.js b/ui/components/app/signature-request/signature-request-data/signature-request-data.js
index 15b1359d8..a809d4a65 100644
--- a/ui/components/app/signature-request/signature-request-data/signature-request-data.js
+++ b/ui/components/app/signature-request/signature-request-data/signature-request-data.js
@@ -19,6 +19,7 @@ import {
TypographyVariant,
TextColor,
} from '../../../../helpers/constants/design-system';
+import { sanitizeString } from '../../../../helpers/utils/util';
function SignatureRequestData({ data }) {
const identities = useSelector(getMemoizedMetaMaskIdentities);
@@ -42,7 +43,7 @@ function SignatureRequestData({ data }) {
typeof value === 'object' ? FONT_WEIGHT.BOLD : FONT_WEIGHT.NORMAL
}
>
- {label.charAt(0).toUpperCase() + label.slice(1)}:{' '}
+ {sanitizeString(label.charAt(0).toUpperCase() + label.slice(1))}:{' '}
{typeof value === 'object' && value !== null ? (
@@ -68,7 +69,7 @@ function SignatureRequestData({ data }) {
/>
) : (
- `${value}`
+ sanitizeString(`${value}`)
)}
)}
diff --git a/ui/components/app/signature-request/signature-request-data/signature-request-data.test.js b/ui/components/app/signature-request/signature-request-data/signature-request-data.test.js
index 7a2f4a186..9ea93fe05 100644
--- a/ui/components/app/signature-request/signature-request-data/signature-request-data.test.js
+++ b/ui/components/app/signature-request/signature-request-data/signature-request-data.test.js
@@ -468,5 +468,55 @@ describe('Signature Request Data', () => {
expect(getByText('0xB0B...0000')).toBeInTheDocument();
});
+
+ it('should escape RTL character in label or value', () => {
+ const messageDataWithRTLCharacters = {
+ ...messageData,
+ message: {
+ ...messageData.message,
+ contents: 'Hello, \u202E Bob!',
+ from: {
+ 'name\u202Ename': 'Cow \u202E Cow',
+ 'wallets\u202Ewallets': [
+ '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
+ '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
+ '0x06195827297c7A80a443b6894d3BDB8824b43896',
+ ],
+ },
+ to: [
+ {
+ 'name\u202Ename': 'Bob \u202E Bob',
+ 'wallets\u202Ewallets': [
+ '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
+ '0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
+ '0xB0B0b0b0b0b0B000000000000000000000000000',
+ ],
+ },
+ ],
+ },
+ types: {
+ ...messageData.message.types,
+ Person: [
+ { name: 'name\u202Ename', type: 'string' },
+ { name: 'wallets\u202Ewallets', type: 'address[]' },
+ ],
+ },
+ };
+ const msgParams = {
+ data: JSON.parse(JSON.stringify(messageDataWithRTLCharacters)),
+ version: 'V4',
+ origin: 'test',
+ };
+ const { getByText, getAllByText } = renderWithProvider(
+ ,
+ store,
+ );
+
+ expect(getByText('Hello, \\u202E Bob!')).toBeInTheDocument();
+ expect(getByText('Cow \\u202E Cow')).toBeInTheDocument();
+ expect(getByText('Bob \\u202E Bob')).toBeInTheDocument();
+ expect(getAllByText('Name\\u202Ename:')).toHaveLength(2);
+ expect(getAllByText('Wallets\\u202Ewallets:')).toHaveLength(2);
+ });
});
});
diff --git a/ui/helpers/utils/util.js b/ui/helpers/utils/util.js
index 1dc1d9274..05befbe17 100644
--- a/ui/helpers/utils/util.js
+++ b/ui/helpers/utils/util.js
@@ -5,10 +5,8 @@ import * as ethUtil from 'ethereumjs-util';
import { DateTime } from 'luxon';
import { getFormattedIpfsUrl } from '@metamask/assets-controllers';
import slip44 from '@metamask/slip44';
+import * as lodash from 'lodash';
import bowser from 'bowser';
-///: BEGIN:ONLY_INCLUDE_IN(flask)
-import { isEqual } from 'lodash';
-///: END:ONLY_INCLUDE_IN
import { CHAIN_IDS } from '../../../shared/constants/network';
import {
toChecksumHexAddress,
@@ -540,9 +538,27 @@ export function isNullish(value) {
export function getSnapDerivationPathName(path, curve) {
const pathMetadata = SNAPS_DERIVATION_PATHS.find(
(derivationPath) =>
- derivationPath.curve === curve && isEqual(derivationPath.path, path),
+ derivationPath.curve === curve &&
+ lodash.isEqual(derivationPath.path, path),
);
return pathMetadata?.name ?? null;
}
///: END:ONLY_INCLUDE_IN
+
+/**
+ * The method escape RTL character in string
+ *
+ * @param {any} value
+ * @returns {(string|*)} escaped string or original param value
+ */
+export const sanitizeString = (value) => {
+ if (!value) {
+ return value;
+ }
+ if (!lodash.isString(value)) {
+ return value;
+ }
+ const regex = /\u202E/giu;
+ return value.replaceAll(regex, '\\u202E');
+};
diff --git a/ui/hooks/useTransactionDisplayData.test.js b/ui/hooks/useTransactionDisplayData.test.js
index 970ee1b4e..e61ee354d 100644
--- a/ui/hooks/useTransactionDisplayData.test.js
+++ b/ui/hooks/useTransactionDisplayData.test.js
@@ -20,6 +20,7 @@ import {
TransactionGroupCategory,
TransactionStatus,
} from '../../shared/constants/transaction';
+import { formatDateWithYearContext } from '../helpers/utils/util';
import * as i18nhooks from './useI18nContext';
import * as useTokenFiatAmountHooks from './useTokenFiatAmount';
import { useTransactionDisplayData } from './useTransactionDisplayData';
@@ -30,7 +31,7 @@ const expectedResults = [
category: TransactionGroupCategory.send,
subtitle: 'To: 0xffe...1a97',
subtitleContainsOrigin: false,
- date: 'May 12, 2020',
+ date: formatDateWithYearContext(1589314601567),
primaryCurrency: '-1 ETH',
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
recipientAddress: '0xffe5bc4e8f1f969934d773fa67da095d2e491a97',
@@ -44,7 +45,7 @@ const expectedResults = [
category: TransactionGroupCategory.send,
subtitle: 'To: 0x0cc...8848',
subtitleContainsOrigin: false,
- date: 'May 12, 2020',
+ date: formatDateWithYearContext(1589314355872),
primaryCurrency: '-2 ETH',
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
recipientAddress: '0x0ccc8aeeaf5ce790f3b448325981a143fdef8848',
@@ -57,7 +58,7 @@ const expectedResults = [
category: TransactionGroupCategory.send,
subtitle: 'To: 0xffe...1a97',
subtitleContainsOrigin: false,
- date: 'May 12, 2020',
+ date: formatDateWithYearContext(1589314345433),
primaryCurrency: '-2 ETH',
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
recipientAddress: '0xffe5bc4e8f1f969934d773fa67da095d2e491a97',
@@ -70,7 +71,7 @@ const expectedResults = [
category: TransactionGroupCategory.receive,
subtitle: 'From: 0x31b...4523',
subtitleContainsOrigin: false,
- date: 'May 12, 2020',
+ date: formatDateWithYearContext(1589314295000),
primaryCurrency: '18.75 ETH',
senderAddress: '0x31b98d14007bdee637298086988a0bbd31184523',
recipientAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
@@ -83,7 +84,7 @@ const expectedResults = [
category: TransactionGroupCategory.receive,
subtitle: 'From: 0x9ec...a149',
subtitleContainsOrigin: false,
- date: 'May 8, 2020',
+ date: formatDateWithYearContext(1588972833000),
primaryCurrency: '0 ETH',
senderAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
recipientAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
@@ -96,7 +97,7 @@ const expectedResults = [
category: TransactionGroupCategory.receive,
subtitle: 'From: 0xee0...febb',
subtitleContainsOrigin: false,
- date: 'May 24, 2020',
+ date: formatDateWithYearContext(1585087013000),
primaryCurrency: '1 ETH',
senderAddress: '0xee014609ef9e09776ac5fe00bdbfef57bcdefebb',
recipientAddress: '0x9eca64466f257793eaa52fcfff5066894b76a149',
@@ -109,7 +110,7 @@ const expectedResults = [
category: TransactionType.swap,
subtitle: '',
subtitleContainsOrigin: false,
- date: 'May 12, 2020',
+ date: formatDateWithYearContext(1585088013000),
primaryCurrency: '+1 ABC',
senderAddress: '0xee014609ef9e09776ac5fe00bdbfef57bcdefebb',
recipientAddress: '0xabca64466f257793eaa52fcfff5066894b76a149',
@@ -122,7 +123,7 @@ const expectedResults = [
category: TransactionGroupCategory.interaction,
subtitle: 'metamask.github.io',
subtitleContainsOrigin: true,
- date: 'May 12, 2020',
+ date: formatDateWithYearContext(1585088013000),
primaryCurrency: '-0 ETH',
senderAddress: '0xee014609ef9e09776ac5fe00bdbfef57bcdefebb',
recipientAddress: undefined,