From 3822274b40676e1bd04d818609b67f7bef2bb9bf Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Tue, 4 Feb 2020 15:26:29 -0800 Subject: [PATCH 1/4] _sendAsync: typecheck payload method and params --- index.js | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/index.js b/index.js index 4bb8ce81..6473064b 100644 --- a/index.js +++ b/index.js @@ -32,7 +32,7 @@ module.exports = MetamaskInpageProvider inherits(MetamaskInpageProvider, SafeEventEmitter) -function MetamaskInpageProvider (connectionStream) { +function MetamaskInpageProvider (connectionStream, shouldSendMetadata = true) { // super constructor SafeEventEmitter.call(this) @@ -151,11 +151,13 @@ function MetamaskInpageProvider (connectionStream) { }) // send website metadata - const domContentLoadedHandler = () => { - sendSiteMetadata(this._rpcEngine) - window.removeEventListener('DOMContentLoaded', domContentLoadedHandler) + if (shouldSendMetadata) { + const domContentLoadedHandler = () => { + sendSiteMetadata(this._rpcEngine) + window.removeEventListener('DOMContentLoaded', domContentLoadedHandler) + } + window.addEventListener('DOMContentLoaded', domContentLoadedHandler) } - window.addEventListener('DOMContentLoaded', domContentLoadedHandler) // indicate that we've connected, for EIP-1193 compliance setTimeout(() => this.emit('connect')) @@ -373,10 +375,26 @@ MetamaskInpageProvider.prototype._sendAsync = function (payload, userCallback, i if (!Array.isArray(payload)) { + if (!payload.method || typeof payload.method !== 'string') { + throw ethErrors.rpc.invalidRequest({ + message: `The request 'method' must be a non-empty string.`, + data: payload, + }) + } + if (!payload.jsonrpc) { payload.jsonrpc = '2.0' } + if (!payload.params) { + payload.params = [] + } else if (!Array.isArray(payload.params)) { + throw ethErrors.rpc.invalidRequest({ + message: `The request 'params' must be an array.`, + data: payload, + }) + } + if ( payload.method === 'eth_accounts' || payload.method === 'eth_requestAccounts' @@ -529,7 +547,6 @@ function getExperimentalApi (instance) { }, }, { - get: (obj, prop) => { if (!instance._state.sentWarnings.experimentalMethods) { From 26e09bba73cdc5c83545fba3446f457fdc93aca3 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Tue, 4 Feb 2020 22:14:29 -0800 Subject: [PATCH 2/4] 4.0.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 52a1c0ca..bcb5ca21 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "metamask-inpage-provider", - "version": "4.0.3", + "version": "4.0.4", "description": "An ethereum provider that connects over a WebExtension port.", "main": "index.js", "scripts": { From a03eeecd7223c1167bd3681015abf6191df53b4e Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Wed, 5 Feb 2020 07:54:34 -0800 Subject: [PATCH 3/4] move req validation to middleware --- index.js | 26 ++++++-------------------- src/utils.js | 13 +++++++++++-- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/index.js b/index.js index 6473064b..97161716 100644 --- a/index.js +++ b/index.js @@ -241,6 +241,8 @@ MetamaskInpageProvider.prototype.send = function (methodOrPayload, params) { ) { // wrap params in array out of kindness + // params have to be an array per EIP 1193, even though JSON RPC + // allows objects if (params === undefined) { params = [] } else if (!Array.isArray(params)) { @@ -253,12 +255,12 @@ MetamaskInpageProvider.prototype.send = function (methodOrPayload, params) { } } - // typecheck payload and payload.method + // typecheck payload, payload.method, and payload.params if ( - Array.isArray(payload) || - typeof params === 'function' || typeof payload !== 'object' || - typeof payload.method !== 'string' + Array.isArray(payload) || + !Array.isArray(params) || + !payload.method || typeof payload.method !== 'string' ) { throw ethErrors.rpc.invalidRequest({ message: messages.errors.invalidParams(), @@ -375,26 +377,10 @@ MetamaskInpageProvider.prototype._sendAsync = function (payload, userCallback, i if (!Array.isArray(payload)) { - if (!payload.method || typeof payload.method !== 'string') { - throw ethErrors.rpc.invalidRequest({ - message: `The request 'method' must be a non-empty string.`, - data: payload, - }) - } - if (!payload.jsonrpc) { payload.jsonrpc = '2.0' } - if (!payload.params) { - payload.params = [] - } else if (!Array.isArray(payload.params)) { - throw ethErrors.rpc.invalidRequest({ - message: `The request 'params' must be an array.`, - data: payload, - }) - } - if ( payload.method === 'eth_accounts' || payload.method === 'eth_requestAccounts' diff --git a/src/utils.js b/src/utils.js index 80242da6..dce5c003 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,6 +1,6 @@ const log = require('loglevel') -const { serializeError } = require('eth-json-rpc-errors') +const { ethErrors, serializeError } = require('eth-json-rpc-errors') const EventEmitter = require('events') const SafeEventEmitter = require('safe-event-emitter') @@ -17,7 +17,16 @@ const SafeEventEmitter = require('safe-event-emitter') * @returns {Function} json-rpc-engine middleware function */ function createErrorMiddleware () { - return (_req, res, next) => { + return (req, res, next) => { + + // json-rpc-engine will terminate the request when it notices this error + if (!req.method || typeof req.method !== 'string') { + res.error = ethErrors.rpc.invalidRequest({ + message: `The request 'method' must be a non-empty string.`, + data: req, + }) + } + next(done => { const { error } = res if (!error) { From 07ed34626d1d3bd4031f138b4910cad2628ab46b Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Wed, 5 Feb 2020 18:39:09 -0800 Subject: [PATCH 4/4] remove duplicate payload.method typecheck --- index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 97161716..53ba394a 100644 --- a/index.js +++ b/index.js @@ -255,12 +255,11 @@ MetamaskInpageProvider.prototype.send = function (methodOrPayload, params) { } } - // typecheck payload, payload.method, and payload.params + // typecheck payload and payload.params if ( typeof payload !== 'object' || Array.isArray(payload) || - !Array.isArray(params) || - !payload.method || typeof payload.method !== 'string' + !Array.isArray(params) ) { throw ethErrors.rpc.invalidRequest({ message: messages.errors.invalidParams(),