From 7e81aaca5d5e091c04682b7ed9713e627f3fc1bc Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Tue, 27 Jan 2026 18:18:14 +0530 Subject: [PATCH 01/11] Adding prototype pollution validation for typed sign messages --- .../src/wallet.test.ts | 119 ++++++++++++++++++ .../eth-json-rpc-middleware/src/wallet.ts | 94 ++++++++++++++ 2 files changed, 213 insertions(+) diff --git a/packages/eth-json-rpc-middleware/src/wallet.test.ts b/packages/eth-json-rpc-middleware/src/wallet.test.ts index 581eee55d80..625e1beb480 100644 --- a/packages/eth-json-rpc-middleware/src/wallet.test.ts +++ b/packages/eth-json-rpc-middleware/src/wallet.test.ts @@ -9,6 +9,17 @@ import type { } from '.'; import { createWalletMiddleware } from '.'; import { createHandleParams, createRequest } from '../test/util/helpers'; +import { JsonRpcEngine } from '@metamask/json-rpc-engine'; + +const DANGEROUS_PROTOTYPE_PROPERTIES = [ + '__proto__', + 'constructor', + 'prototype', + '__defineGetter__', + '__defineSetter__', + '__lookupGetter__', + '__lookupSetter__', +] as const; const testAddresses = [ '0xbe93f9bacbcffc8ee6663f2647917ed7a20a57bb', @@ -20,6 +31,14 @@ const testTxHash = const testMsgSig = '0x68dc980608bceb5f99f691e62c32caccaee05317309015e9454eba1a14c3cd4505d1dd098b8339801239c9bcaac3c4df95569dcf307108b92f68711379be14d81c'; +function createTestSetup() { + const getAccounts = async (): Promise => []; + const engine = JsonRpcEngineV2.create({ + middleware: [createWalletMiddleware({ getAccounts })], + }); + return { engine }; +} + describe('wallet', () => { describe('accounts', () => { it('returns null for coinbase when no accounts', async () => { @@ -903,4 +922,104 @@ describe('wallet', () => { expect(ecrecoverResult).toStrictEqual(signParams.addressHex); }); }); + + describe('prototype pollution validation', () => { + describe('signTypedData (V1)', () => { + DANGEROUS_PROTOTYPE_PROPERTIES.forEach((dangerousProperty) => { + it(`should throw if value contains nested ${dangerousProperty}`, async () => { + const getAccounts = async () => testAddresses.slice(); + const processTypedMessage = async () => testMsgSig; + const engine = JsonRpcEngineV2.create({ + middleware: [createWalletMiddleware({ getAccounts, processTypedMessage })], + }); + + const value = {}; + Object.defineProperty(value, dangerousProperty, { + value: 'malicious', + enumerable: true, + }); + const message = [{ type: 'object', name: 'data', value }]; + const payload = { + method: 'eth_signTypedData', + params: [message, testAddresses[0]], + }; + + await expect( + engine.handle(...createHandleParams(payload)), + ).rejects.toThrow('Invalid input.'); + }); + }); + }); + + describe('signTypedDataV3', () => { + DANGEROUS_PROTOTYPE_PROPERTIES.forEach((dangerousProperty) => { + it(`should throw if message contains ${dangerousProperty}`, async () => { + const getAccounts = async () => testAddresses.slice(); + const processTypedMessageV3 = async () => testMsgSig; + const engine = JsonRpcEngineV2.create({ + middleware: [createWalletMiddleware({ getAccounts, processTypedMessageV3 })], + }); + + const msgObj = {}; + Object.defineProperty(msgObj, dangerousProperty, { + value: 'malicious', + enumerable: true, + }); + const message = { + types: { + EIP712Domain: [{ name: 'name', type: 'string' }], + }, + primaryType: 'EIP712Domain', + domain: {}, + message: msgObj, + }; + + const payload = { + method: 'eth_signTypedData_v3', + params: [testAddresses[0], JSON.stringify(message)], + }; + + await expect( + engine.handle(...createHandleParams(payload)), + ).rejects.toThrow('Invalid input.'); + }); + }); + }); + + describe('signTypedDataV4', () => { + DANGEROUS_PROTOTYPE_PROPERTIES.forEach((dangerousProperty) => { + it(`should throw if message contains ${dangerousProperty}`, async () => { + const getAccounts = async () => testAddresses.slice(); + const processTypedMessageV4 = async () => testMsgSig; + const engine = JsonRpcEngineV2.create({ + middleware: [createWalletMiddleware({ getAccounts, processTypedMessageV4 })], + }); + + const msgObj = {}; + Object.defineProperty(msgObj, dangerousProperty, { + value: 'malicious', + enumerable: true, + }); + const message = { + types: { + EIP712Domain: [{ name: 'name', type: 'string' }], + Permit: [{ name: 'owner', type: 'address' }], + }, + primaryType: 'Permit', + domain: {}, + message: msgObj, + }; + + const payload = { + method: 'eth_signTypedData_v4', + params: [testAddresses[0], JSON.stringify(message)], + }; + + await expect( + engine.handle(...createHandleParams(payload)), + ).rejects.toThrow('Invalid input.'); + }); + }); + }); + }); }); diff --git a/packages/eth-json-rpc-middleware/src/wallet.ts b/packages/eth-json-rpc-middleware/src/wallet.ts index f5893c22c44..c64c38f4fc9 100644 --- a/packages/eth-json-rpc-middleware/src/wallet.ts +++ b/packages/eth-json-rpc-middleware/src/wallet.ts @@ -323,6 +323,7 @@ export function createWalletMiddleware({ const message = params[0]; const address = await validateAndNormalizeKeyholder(params[1], context); const version = 'V1'; + validateTypedDataV1ForPrototypePollution(message); // Not using nullish coalescing, since `params` may be `null`. // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const extraParams = params[2] || {}; @@ -366,6 +367,7 @@ export function createWalletMiddleware({ const message = normalizeTypedMessage(params[1]); validatePrimaryType(message); validateVerifyingContract(message); + validateTypedDataForPrototypePollution(message); const version = 'V3'; const msgParams: TypedMessageParams = { data: message, @@ -406,6 +408,7 @@ export function createWalletMiddleware({ const message = normalizeTypedMessage(params[1]); validatePrimaryType(message); validateVerifyingContract(message); + validateTypedDataForPrototypePollution(message); const version = 'V4'; const msgParams: TypedMessageParams = { data: message, @@ -648,3 +651,94 @@ function validateVerifyingContract(data: string): void { throw rpcErrors.invalidInput(); } } + + +const DANGEROUS_PROTOTYPE_PROPERTIES = [ + '__proto__', + 'constructor', + 'prototype', + '__defineGetter__', + '__defineSetter__', + '__lookupGetter__', + '__lookupSetter__', +] as const; + +/** + * Checks if a property name is dangerous for prototype pollution. + * + * @param key - The property name to check + * @returns True if the property name is dangerous + */ +function isDangerousProperty(key: string): boolean { + return (DANGEROUS_PROTOTYPE_PROPERTIES as readonly string[]).includes(key); +} + +/** + * Recursively checks an object for dangerous prototype pollution properties. + * + * @param obj - The object to check + * @throws rpcErrors.invalidInput() if a dangerous property is found + */ +function checkObjectForPrototypePollution(obj: unknown): void { + if (obj === null || obj === undefined) { + return; + } + + if (Array.isArray(obj)) { + for (const item of obj) { + checkObjectForPrototypePollution(item); + } + return; + } + + if (typeof obj === 'object') { + for (const key of Object.getOwnPropertyNames( + obj as Record, + )) { + if (isDangerousProperty(key)) { + throw rpcErrors.invalidInput(); + } + checkObjectForPrototypePollution((obj as Record)[key]); + } + } +} + +/** + * Validates V1 typed data (array format) for prototype pollution attacks. + * V1 format: [{ type: 'string', name: 'fieldName', value: 'data' }, ...] + * + * @param data - The V1 typed data array to validate + * @throws rpcErrors.invalidInput() if prototype pollution is detected + */ +function validateTypedDataV1ForPrototypePollution( + data: Record[], +): void { + if (!data || !Array.isArray(data)) { + return; + } + + for (const item of data) { + if (item && typeof item === 'object') { + // Only check the 'value' field (the message data) for dangerous properties + if (item.value !== null && typeof item.value === 'object') { + checkObjectForPrototypePollution(item.value); + } + } + } +} + +/** + * Validates V3/V4 typed data (EIP-712 format) for prototype pollution attacks. + * Only checks the message field for dangerous properties. + * + * @param data - The stringified typed data to validate + * @throws rpcErrors.invalidInput() if prototype pollution is detected + */ +function validateTypedDataForPrototypePollution(data: string): void { + const { message } = parseTypedMessage(data); + + // Check message recursively for dangerous properties + if (message !== undefined) { + checkObjectForPrototypePollution(message); + } +} From e81ac09c6a1c2a5363790e894ccd414d09810e2a Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Tue, 27 Jan 2026 18:53:03 +0530 Subject: [PATCH 02/11] docs: add changelog entry for prototype pollution validation - Added entry for prototype pollution validation feature - Added entry for test fix - Follows Keep a Changelog format --- packages/eth-json-rpc-middleware/CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/eth-json-rpc-middleware/CHANGELOG.md b/packages/eth-json-rpc-middleware/CHANGELOG.md index c95e3a8da36..e380c30005a 100644 --- a/packages/eth-json-rpc-middleware/CHANGELOG.md +++ b/packages/eth-json-rpc-middleware/CHANGELOG.md @@ -7,11 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add prototype pollution validation for `signTypedData` methods (V1, V3, V4) to block dangerous properties (`__proto__`, `constructor`, `prototype`, etc.) in message data + ### Changed - Bump `@metamask/eth-block-tracker` from `^15.0.0` to `^15.0.1` ([#7642](https://github.com/MetaMask/core/pull/7642)) - Bump `@metamask/json-rpc-engine` from `^10.2.0` to `^10.2.1` ([#7642](https://github.com/MetaMask/core/pull/7642)) +### Fixed + +- Fix prototype pollution tests to use `createHandleParams` helper for proper context setup + ## [23.0.0] ### Added From 3a4dd23e8bc183b6c1db79ec2a382ad9fcf83a40 Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Tue, 27 Jan 2026 18:55:25 +0530 Subject: [PATCH 03/11] Adding changelog entry --- packages/eth-json-rpc-middleware/CHANGELOG.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/eth-json-rpc-middleware/CHANGELOG.md b/packages/eth-json-rpc-middleware/CHANGELOG.md index e380c30005a..440a9b413b9 100644 --- a/packages/eth-json-rpc-middleware/CHANGELOG.md +++ b/packages/eth-json-rpc-middleware/CHANGELOG.md @@ -9,17 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Add prototype pollution validation for `signTypedData` methods (V1, V3, V4) to block dangerous properties (`__proto__`, `constructor`, `prototype`, etc.) in message data +- Add prototype pollution validation for `signTypedData` methods (V1, V3, V4) to block dangerous properties (`__proto__`, `constructor`, `prototype`, etc.) in message data. ([#7732](https://github.com/MetaMask/core/pull/7732)) ### Changed - Bump `@metamask/eth-block-tracker` from `^15.0.0` to `^15.0.1` ([#7642](https://github.com/MetaMask/core/pull/7642)) - Bump `@metamask/json-rpc-engine` from `^10.2.0` to `^10.2.1` ([#7642](https://github.com/MetaMask/core/pull/7642)) -### Fixed - -- Fix prototype pollution tests to use `createHandleParams` helper for proper context setup - ## [23.0.0] ### Added From ed61d9cf041d0e7d93d5db1343ca7b8ac784b0f9 Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Tue, 27 Jan 2026 18:57:31 +0530 Subject: [PATCH 04/11] Adding changelog entry --- packages/eth-json-rpc-middleware/src/wallet.test.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/eth-json-rpc-middleware/src/wallet.test.ts b/packages/eth-json-rpc-middleware/src/wallet.test.ts index 625e1beb480..ac185199d46 100644 --- a/packages/eth-json-rpc-middleware/src/wallet.test.ts +++ b/packages/eth-json-rpc-middleware/src/wallet.test.ts @@ -9,7 +9,6 @@ import type { } from '.'; import { createWalletMiddleware } from '.'; import { createHandleParams, createRequest } from '../test/util/helpers'; -import { JsonRpcEngine } from '@metamask/json-rpc-engine'; const DANGEROUS_PROTOTYPE_PROPERTIES = [ '__proto__', @@ -30,14 +29,6 @@ const testTxHash = '0xceb3240213640d89419829f3e8011d015af7a7ab3b54c14fdf125620ce5b8697'; const testMsgSig = '0x68dc980608bceb5f99f691e62c32caccaee05317309015e9454eba1a14c3cd4505d1dd098b8339801239c9bcaac3c4df95569dcf307108b92f68711379be14d81c'; - -function createTestSetup() { - const getAccounts = async (): Promise => []; - const engine = JsonRpcEngineV2.create({ - middleware: [createWalletMiddleware({ getAccounts })], - }); - return { engine }; -} describe('wallet', () => { describe('accounts', () => { From d9407e66c3349cb52b5af2f4e865338679c955da Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Tue, 27 Jan 2026 19:12:12 +0530 Subject: [PATCH 05/11] fix(lint): add return type annotations to prototype pollution tests - Added Promise return type to getAccounts functions - Added Promise return type to processTypedMessage functions - Fixed prettier formatting issues - All lint checks now pass --- .../src/wallet.test.ts | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/packages/eth-json-rpc-middleware/src/wallet.test.ts b/packages/eth-json-rpc-middleware/src/wallet.test.ts index ac185199d46..67bddc37e84 100644 --- a/packages/eth-json-rpc-middleware/src/wallet.test.ts +++ b/packages/eth-json-rpc-middleware/src/wallet.test.ts @@ -29,7 +29,7 @@ const testTxHash = '0xceb3240213640d89419829f3e8011d015af7a7ab3b54c14fdf125620ce5b8697'; const testMsgSig = '0x68dc980608bceb5f99f691e62c32caccaee05317309015e9454eba1a14c3cd4505d1dd098b8339801239c9bcaac3c4df95569dcf307108b92f68711379be14d81c'; - + describe('wallet', () => { describe('accounts', () => { it('returns null for coinbase when no accounts', async () => { @@ -918,10 +918,13 @@ describe('wallet', () => { describe('signTypedData (V1)', () => { DANGEROUS_PROTOTYPE_PROPERTIES.forEach((dangerousProperty) => { it(`should throw if value contains nested ${dangerousProperty}`, async () => { - const getAccounts = async () => testAddresses.slice(); - const processTypedMessage = async () => testMsgSig; + const getAccounts = async (): Promise => + testAddresses.slice(); + const processTypedMessage = async (): Promise => testMsgSig; const engine = JsonRpcEngineV2.create({ - middleware: [createWalletMiddleware({ getAccounts, processTypedMessage })], + middleware: [ + createWalletMiddleware({ getAccounts, processTypedMessage }), + ], }); const value = {}; @@ -945,12 +948,15 @@ describe('wallet', () => { describe('signTypedDataV3', () => { DANGEROUS_PROTOTYPE_PROPERTIES.forEach((dangerousProperty) => { it(`should throw if message contains ${dangerousProperty}`, async () => { - const getAccounts = async () => testAddresses.slice(); - const processTypedMessageV3 = async () => testMsgSig; + const getAccounts = async (): Promise => + testAddresses.slice(); + const processTypedMessageV3 = async (): Promise => testMsgSig; const engine = JsonRpcEngineV2.create({ - middleware: [createWalletMiddleware({ getAccounts, processTypedMessageV3 })], + middleware: [ + createWalletMiddleware({ getAccounts, processTypedMessageV3 }), + ], }); - + const msgObj = {}; Object.defineProperty(msgObj, dangerousProperty, { value: 'malicious', @@ -980,10 +986,13 @@ describe('wallet', () => { describe('signTypedDataV4', () => { DANGEROUS_PROTOTYPE_PROPERTIES.forEach((dangerousProperty) => { it(`should throw if message contains ${dangerousProperty}`, async () => { - const getAccounts = async () => testAddresses.slice(); - const processTypedMessageV4 = async () => testMsgSig; + const getAccounts = async (): Promise => + testAddresses.slice(); + const processTypedMessageV4 = async (): Promise => testMsgSig; const engine = JsonRpcEngineV2.create({ - middleware: [createWalletMiddleware({ getAccounts, processTypedMessageV4 })], + middleware: [ + createWalletMiddleware({ getAccounts, processTypedMessageV4 }), + ], }); const msgObj = {}; From 1fd6d8ac6d4f35bc52bfb2af33ab82ab528e5cd4 Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Tue, 27 Jan 2026 19:17:41 +0530 Subject: [PATCH 06/11] update --- packages/eth-json-rpc-middleware/src/wallet.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/eth-json-rpc-middleware/src/wallet.ts b/packages/eth-json-rpc-middleware/src/wallet.ts index c64c38f4fc9..fc343748c35 100644 --- a/packages/eth-json-rpc-middleware/src/wallet.ts +++ b/packages/eth-json-rpc-middleware/src/wallet.ts @@ -652,7 +652,6 @@ function validateVerifyingContract(data: string): void { } } - const DANGEROUS_PROTOTYPE_PROPERTIES = [ '__proto__', 'constructor', From 0a6ec9b14d5cf4b209d76c4293da75e25ff9f5d9 Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Thu, 29 Jan 2026 10:32:48 +0530 Subject: [PATCH 07/11] update --- .../src/utils/validation.ts | 92 +++++++++++++++++++ .../eth-json-rpc-middleware/src/wallet.ts | 92 +------------------ 2 files changed, 94 insertions(+), 90 deletions(-) diff --git a/packages/eth-json-rpc-middleware/src/utils/validation.ts b/packages/eth-json-rpc-middleware/src/utils/validation.ts index 01293dd6eeb..a090b3333d9 100644 --- a/packages/eth-json-rpc-middleware/src/utils/validation.ts +++ b/packages/eth-json-rpc-middleware/src/utils/validation.ts @@ -4,6 +4,7 @@ import { validate } from '@metamask/superstruct'; import type { Hex } from '@metamask/utils'; import type { WalletMiddlewareContext } from '../wallet'; +import { parseTypedMessage } from './normalize'; /** * Validates and normalizes a keyholder address for transaction- and @@ -96,3 +97,94 @@ function formatValidationError(error: StructError, message: string): string { ) .join('\n')}`; } + + +const DANGEROUS_PROTOTYPE_PROPERTIES = [ + '__proto__', + 'constructor', + 'prototype', + '__defineGetter__', + '__defineSetter__', + '__lookupGetter__', + '__lookupSetter__', +] as const; + +/** + * Checks if a property name is dangerous for prototype pollution. + * + * @param key - The property name to check + * @returns True if the property name is dangerous + */ +function isDangerousProperty(key: string): boolean { + return (DANGEROUS_PROTOTYPE_PROPERTIES as readonly string[]).includes(key); +} + +/** + * Recursively checks an object for dangerous prototype pollution properties. + * + * @param obj - The object to check + * @throws rpcErrors.invalidInput() if a dangerous property is found + */ +function checkObjectForPrototypePollution(obj: unknown): void { + if (obj === null || obj === undefined) { + return; + } + + if (Array.isArray(obj)) { + for (const item of obj) { + checkObjectForPrototypePollution(item); + } + return; + } + + if (typeof obj === 'object') { + for (const key of Object.getOwnPropertyNames( + obj as Record, + )) { + if (isDangerousProperty(key)) { + throw rpcErrors.invalidInput(); + } + checkObjectForPrototypePollution((obj as Record)[key]); + } + } +} + +/** + * Validates V1 typed data (array format) for prototype pollution attacks. + * V1 format: [{ type: 'string', name: 'fieldName', value: 'data' }, ...] + * + * @param data - The V1 typed data array to validate + * @throws rpcErrors.invalidInput() if prototype pollution is detected + */ +export function validateTypedDataV1ForPrototypePollution( + data: Record[], +): void { + if (!data || !Array.isArray(data)) { + return; + } + + for (const item of data) { + if (item && typeof item === 'object') { + // Only check the 'value' field (the message data) for dangerous properties + if (item.value !== null && typeof item.value === 'object') { + checkObjectForPrototypePollution(item.value); + } + } + } +} + +/** + * Validates V3/V4 typed data (EIP-712 format) for prototype pollution attacks. + * Only checks the message field for dangerous properties. + * + * @param data - The stringified typed data to validate + * @throws rpcErrors.invalidInput() if prototype pollution is detected + */ +export function validateTypedDataForPrototypePollution(data: string): void { + const { message } = parseTypedMessage(data); + + // Check message recursively for dangerous properties + if (message !== undefined) { + checkObjectForPrototypePollution(message); + } +} diff --git a/packages/eth-json-rpc-middleware/src/wallet.ts b/packages/eth-json-rpc-middleware/src/wallet.ts index fc343748c35..24394190640 100644 --- a/packages/eth-json-rpc-middleware/src/wallet.ts +++ b/packages/eth-json-rpc-middleware/src/wallet.ts @@ -23,6 +23,8 @@ import { normalizeTypedMessage, parseTypedMessage } from './utils/normalize'; import { resemblesAddress, validateAndNormalizeKeyholder as validateKeyholder, + validateTypedDataForPrototypePollution, + validateTypedDataV1ForPrototypePollution, } from './utils/validation'; export type TransactionParams = { @@ -651,93 +653,3 @@ function validateVerifyingContract(data: string): void { throw rpcErrors.invalidInput(); } } - -const DANGEROUS_PROTOTYPE_PROPERTIES = [ - '__proto__', - 'constructor', - 'prototype', - '__defineGetter__', - '__defineSetter__', - '__lookupGetter__', - '__lookupSetter__', -] as const; - -/** - * Checks if a property name is dangerous for prototype pollution. - * - * @param key - The property name to check - * @returns True if the property name is dangerous - */ -function isDangerousProperty(key: string): boolean { - return (DANGEROUS_PROTOTYPE_PROPERTIES as readonly string[]).includes(key); -} - -/** - * Recursively checks an object for dangerous prototype pollution properties. - * - * @param obj - The object to check - * @throws rpcErrors.invalidInput() if a dangerous property is found - */ -function checkObjectForPrototypePollution(obj: unknown): void { - if (obj === null || obj === undefined) { - return; - } - - if (Array.isArray(obj)) { - for (const item of obj) { - checkObjectForPrototypePollution(item); - } - return; - } - - if (typeof obj === 'object') { - for (const key of Object.getOwnPropertyNames( - obj as Record, - )) { - if (isDangerousProperty(key)) { - throw rpcErrors.invalidInput(); - } - checkObjectForPrototypePollution((obj as Record)[key]); - } - } -} - -/** - * Validates V1 typed data (array format) for prototype pollution attacks. - * V1 format: [{ type: 'string', name: 'fieldName', value: 'data' }, ...] - * - * @param data - The V1 typed data array to validate - * @throws rpcErrors.invalidInput() if prototype pollution is detected - */ -function validateTypedDataV1ForPrototypePollution( - data: Record[], -): void { - if (!data || !Array.isArray(data)) { - return; - } - - for (const item of data) { - if (item && typeof item === 'object') { - // Only check the 'value' field (the message data) for dangerous properties - if (item.value !== null && typeof item.value === 'object') { - checkObjectForPrototypePollution(item.value); - } - } - } -} - -/** - * Validates V3/V4 typed data (EIP-712 format) for prototype pollution attacks. - * Only checks the message field for dangerous properties. - * - * @param data - The stringified typed data to validate - * @throws rpcErrors.invalidInput() if prototype pollution is detected - */ -function validateTypedDataForPrototypePollution(data: string): void { - const { message } = parseTypedMessage(data); - - // Check message recursively for dangerous properties - if (message !== undefined) { - checkObjectForPrototypePollution(message); - } -} From a64472527cc50de6f765c26281975103dda51e59 Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Thu, 29 Jan 2026 14:09:45 +0530 Subject: [PATCH 08/11] update --- .../eth-json-rpc-middleware/src/utils/validation.ts | 5 ++--- packages/eth-json-rpc-middleware/src/wallet.test.ts | 11 +---------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/packages/eth-json-rpc-middleware/src/utils/validation.ts b/packages/eth-json-rpc-middleware/src/utils/validation.ts index a090b3333d9..a29d8a13a29 100644 --- a/packages/eth-json-rpc-middleware/src/utils/validation.ts +++ b/packages/eth-json-rpc-middleware/src/utils/validation.ts @@ -3,8 +3,8 @@ import type { Struct, StructError } from '@metamask/superstruct'; import { validate } from '@metamask/superstruct'; import type { Hex } from '@metamask/utils'; -import type { WalletMiddlewareContext } from '../wallet'; import { parseTypedMessage } from './normalize'; +import type { WalletMiddlewareContext } from '../wallet'; /** * Validates and normalizes a keyholder address for transaction- and @@ -98,8 +98,7 @@ function formatValidationError(error: StructError, message: string): string { .join('\n')}`; } - -const DANGEROUS_PROTOTYPE_PROPERTIES = [ +export const DANGEROUS_PROTOTYPE_PROPERTIES = [ '__proto__', 'constructor', 'prototype', diff --git a/packages/eth-json-rpc-middleware/src/wallet.test.ts b/packages/eth-json-rpc-middleware/src/wallet.test.ts index 67bddc37e84..3c8d69fd36e 100644 --- a/packages/eth-json-rpc-middleware/src/wallet.test.ts +++ b/packages/eth-json-rpc-middleware/src/wallet.test.ts @@ -9,16 +9,7 @@ import type { } from '.'; import { createWalletMiddleware } from '.'; import { createHandleParams, createRequest } from '../test/util/helpers'; - -const DANGEROUS_PROTOTYPE_PROPERTIES = [ - '__proto__', - 'constructor', - 'prototype', - '__defineGetter__', - '__defineSetter__', - '__lookupGetter__', - '__lookupSetter__', -] as const; +import { DANGEROUS_PROTOTYPE_PROPERTIES } from './utils/validation'; const testAddresses = [ '0xbe93f9bacbcffc8ee6663f2647917ed7a20a57bb', From 9611103dfc5cef4f57d189eaeeb089c8dbb26e75 Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Thu, 29 Jan 2026 15:12:05 +0530 Subject: [PATCH 09/11] update --- packages/eth-json-rpc-middleware/src/wallet.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eth-json-rpc-middleware/src/wallet.test.ts b/packages/eth-json-rpc-middleware/src/wallet.test.ts index 3c8d69fd36e..7cc359bb316 100644 --- a/packages/eth-json-rpc-middleware/src/wallet.test.ts +++ b/packages/eth-json-rpc-middleware/src/wallet.test.ts @@ -7,9 +7,9 @@ import type { TypedMessageParams, TypedMessageV1Params, } from '.'; +import { DANGEROUS_PROTOTYPE_PROPERTIES } from './utils/validation'; import { createWalletMiddleware } from '.'; import { createHandleParams, createRequest } from '../test/util/helpers'; -import { DANGEROUS_PROTOTYPE_PROPERTIES } from './utils/validation'; const testAddresses = [ '0xbe93f9bacbcffc8ee6663f2647917ed7a20a57bb', From 93df9232be04343e1cfc31c0c59eee82c8c71b02 Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Thu, 29 Jan 2026 15:19:34 +0530 Subject: [PATCH 10/11] update --- packages/eth-json-rpc-middleware/src/wallet.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eth-json-rpc-middleware/src/wallet.test.ts b/packages/eth-json-rpc-middleware/src/wallet.test.ts index 7cc359bb316..24886bb2605 100644 --- a/packages/eth-json-rpc-middleware/src/wallet.test.ts +++ b/packages/eth-json-rpc-middleware/src/wallet.test.ts @@ -1,6 +1,7 @@ import { MessageTypes, TypedMessage } from '@metamask/eth-sig-util'; import { JsonRpcEngineV2 } from '@metamask/json-rpc-engine/v2'; +import { createHandleParams, createRequest } from '../test/util/helpers'; import type { MessageParams, TransactionParams, @@ -9,7 +10,6 @@ import type { } from '.'; import { DANGEROUS_PROTOTYPE_PROPERTIES } from './utils/validation'; import { createWalletMiddleware } from '.'; -import { createHandleParams, createRequest } from '../test/util/helpers'; const testAddresses = [ '0xbe93f9bacbcffc8ee6663f2647917ed7a20a57bb', From 9355180540f890b81f6f64f0c42fd794866d4cf7 Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Thu, 29 Jan 2026 15:26:10 +0530 Subject: [PATCH 11/11] update --- packages/eth-json-rpc-middleware/src/wallet.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/eth-json-rpc-middleware/src/wallet.test.ts b/packages/eth-json-rpc-middleware/src/wallet.test.ts index 24886bb2605..03c456325f8 100644 --- a/packages/eth-json-rpc-middleware/src/wallet.test.ts +++ b/packages/eth-json-rpc-middleware/src/wallet.test.ts @@ -1,15 +1,15 @@ import { MessageTypes, TypedMessage } from '@metamask/eth-sig-util'; import { JsonRpcEngineV2 } from '@metamask/json-rpc-engine/v2'; -import { createHandleParams, createRequest } from '../test/util/helpers'; import type { MessageParams, TransactionParams, TypedMessageParams, TypedMessageV1Params, } from '.'; -import { DANGEROUS_PROTOTYPE_PROPERTIES } from './utils/validation'; import { createWalletMiddleware } from '.'; +import { DANGEROUS_PROTOTYPE_PROPERTIES } from './utils/validation'; +import { createHandleParams, createRequest } from '../test/util/helpers'; const testAddresses = [ '0xbe93f9bacbcffc8ee6663f2647917ed7a20a57bb',