diff --git a/app/scripts/lib/ppom/ppom-util.test.ts b/app/scripts/lib/ppom/ppom-util.test.ts index 8acb6dd9788c..d3ab62b09d88 100644 --- a/app/scripts/lib/ppom/ppom-util.test.ts +++ b/app/scripts/lib/ppom/ppom-util.test.ts @@ -10,7 +10,7 @@ import { SignatureController, SignatureRequest, } from '@metamask/signature-controller'; -import { Hex } from '@metamask/utils'; +import { Hex, JsonRpcRequest } from '@metamask/utils'; import { BlockaidReason, BlockaidResultType, @@ -22,6 +22,8 @@ import { AppStateController } from '../../controllers/app-state-controller'; import { generateSecurityAlertId, isChainSupported, + METHOD_SIGN_TYPED_DATA_V3, + METHOD_SIGN_TYPED_DATA_V4, updateSecurityAlertResponse, validateRequestWithPPOM, } from './ppom-util'; @@ -57,6 +59,10 @@ const TRANSACTION_PARAMS_MOCK_1: TransactionParams = { value: '0x123', }; +const SIGN_TYPED_DATA_PARAMS_MOCK_1 = '0x123'; +const SIGN_TYPED_DATA_PARAMS_MOCK_2 = + '{"primaryType":"Permit","domain":{},"types":{}}'; + const TRANSACTION_PARAMS_MOCK_2: TransactionParams = { ...TRANSACTION_PARAMS_MOCK_1, to: '0x456', @@ -259,6 +265,48 @@ describe('PPOM Utils', () => { ); }); + // @ts-expect-error This is missing from the Mocha type definitions + it.each([METHOD_SIGN_TYPED_DATA_V3, METHOD_SIGN_TYPED_DATA_V4])( + 'sanitizes request params if method is %s', + async (method: string) => { + const ppom = createPPOMMock(); + const ppomController = createPPOMControllerMock(); + + ppomController.usePPOM.mockImplementation( + (callback) => + // eslint-disable-next-line @typescript-eslint/no-explicit-any + callback(ppom as any) as any, + ); + + const firstTwoParams = [ + SIGN_TYPED_DATA_PARAMS_MOCK_1, + SIGN_TYPED_DATA_PARAMS_MOCK_2, + ]; + + const unwantedParams = [{}, undefined, 1, null]; + + const params = [...firstTwoParams, ...unwantedParams]; + + const request = { + ...REQUEST_MOCK, + method, + params, + } as unknown as JsonRpcRequest; + + await validateRequestWithPPOM({ + ...validateRequestWithPPOMOptionsBase, + ppomController, + request, + }); + + expect(ppom.validateJsonRpc).toHaveBeenCalledTimes(1); + expect(ppom.validateJsonRpc).toHaveBeenCalledWith({ + ...request, + params: firstTwoParams, + }); + }, + ); + it('updates response indicating chain is not supported', async () => { const ppomController = {} as PPOMController; const CHAIN_ID_UNSUPPORTED_MOCK = '0x2'; diff --git a/app/scripts/lib/ppom/ppom-util.ts b/app/scripts/lib/ppom/ppom-util.ts index d27ec6c8e505..6572aa3c3839 100644 --- a/app/scripts/lib/ppom/ppom-util.ts +++ b/app/scripts/lib/ppom/ppom-util.ts @@ -29,6 +29,8 @@ import { const { sentry } = global; const METHOD_SEND_TRANSACTION = 'eth_sendTransaction'; +export const METHOD_SIGN_TYPED_DATA_V3 = 'eth_signTypedData_v3'; +export const METHOD_SIGN_TYPED_DATA_V4 = 'eth_signTypedData_v4'; const SECURITY_ALERT_RESPONSE_ERROR = { result_type: BlockaidResultType.Errored, @@ -169,7 +171,7 @@ function normalizePPOMRequest( request, ) ) { - return request; + return sanitizeRequest(request); } const transactionParams = request.params[0]; @@ -181,6 +183,22 @@ function normalizePPOMRequest( }; } +function sanitizeRequest(request: JsonRpcRequest): JsonRpcRequest { + // This is a temporary fix to prevent a PPOM bypass + if ( + request.method === METHOD_SIGN_TYPED_DATA_V4 || + request.method === METHOD_SIGN_TYPED_DATA_V3 + ) { + if (Array.isArray(request.params)) { + return { + ...request, + params: request.params.slice(0, 2), + }; + } + } + return request; +} + function getErrorMessage(error: unknown) { if (error instanceof Error) { return `${error.name}: ${error.message}`;