Skip to content

Commit 413fd7f

Browse files
authored
chore: final pre-audit fixes (#37)
* chore: final pre-audit fixes * chore: update shasum * chore: fix test * chore: fix linter
1 parent a256fe2 commit 413fd7f

File tree

11 files changed

+70
-50
lines changed

11 files changed

+70
-50
lines changed

packages/api/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ import type http from 'http';
1313
import custodianRequests from './custodian/requests';
1414
import { methodMapping } from './method-mapping';
1515
import doc from './openrpc.json';
16+
import clearRequestsHandler from './routes/clearRequestsHandler';
1617
import listRequestsHandler from './routes/listRequestsHandler';
1718
import tokenHandler from './routes/token-handler';
1819
import type { UpdateSignedMessageRequest } from './routes/updateSignedMessageHandler';
1920
import updateSignedMessageHandler from './routes/updateSignedMessageHandler';
2021
import type { UpdateTransactionRequest } from './routes/updateTransactionHandler';
2122
import updateTransactionHandler from './routes/updateTransactionHandler';
22-
import clearRequestsHandler from './routes/clearRequestsHandler';
2323

2424
dotenv.config();
2525

packages/snap/snap.manifest.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"url": "git+https://github.com/MetaMask/snap-institutional-wallet.git"
88
},
99
"source": {
10-
"shasum": "xC69NMxzQ9d+X0HrsOyJJM6Pna8zpxzeSdt3WVYySaw=",
10+
"shasum": "fxx/F8vsR2zv5EvcSLSyb2tXsCvDAYQx/2vclozmAzA=",
1111
"location": {
1212
"npm": {
1313
"filePath": "dist/bundle.js",

packages/snap/src/features/homepage/components/CustodianList.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export const CustodianList: SnapComponent<CustodianListProps> = ({
7070
solution
7171
</Text>
7272
{custodianMetadata
73-
.filter((custodian) => custodian.enabled)
73+
.filter((custodian) => custodian.production)
7474
.map((custodian) => (
7575
<Section
7676
key={custodian.name}

packages/snap/src/index.ts

+11-10
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1+
/* eslint-disable @typescript-eslint/no-throw-literal */
12
import type { JsonRpcRequest } from '@metamask/keyring-api';
2-
import {
3-
MethodNotSupportedError,
4-
handleKeyringRequest,
5-
} from '@metamask/keyring-api';
3+
import { handleKeyringRequest } from '@metamask/keyring-api';
64
import {
75
type UserInputEvent,
86
type OnCronjobHandler,
97
type OnUserInputHandler,
108
type OnHomePageHandler,
119
UnauthorizedError,
10+
MethodNotFoundError,
1211
} from '@metamask/snaps-sdk';
1312
import type {
1413
Json,
@@ -34,6 +33,7 @@ import type { SnapContext } from './lib/types/Context';
3433
import { CustodianApiMap, CustodianType } from './lib/types/CustodianType';
3534
import logger from './logger';
3635
import { InternalMethod, originPermissions } from './permissions';
36+
// @audit - this file needs unittests
3737

3838
/**
3939
* Verify if the caller can call the requested method.
@@ -155,17 +155,17 @@ export const onRpcRequest: OnRpcRequestHandler = async ({
155155
const requestManager = await getRequestManager();
156156
return await requestManager.clearAllRequests();
157157
}
158-
throw new MethodNotSupportedError(request.method);
158+
throw new MethodNotFoundError(request.method);
159159
}
160160

161161
default: {
162-
throw new MethodNotSupportedError(request.method); // @audit-info or MethodNotFoundError 👉 https://docs.metamask.io/snaps/how-to/communicate-errors/#import-and-throw-errors
162+
throw new MethodNotFoundError(request.method);
163163
}
164164
}
165165
};
166166

167167
export const onKeyringRequest: OnKeyringRequestHandler = async ({
168-
origin, // @audit specify ts types
168+
origin,
169169
request,
170170
}: {
171171
origin: string;
@@ -176,16 +176,17 @@ export const onKeyringRequest: OnKeyringRequestHandler = async ({
176176
JSON.stringify(request, undefined, 2),
177177
);
178178

179+
// assert(request.params, KeyringRequestStruct);
180+
179181
// Check if origin is allowed to call method.
180182
if (!hasPermission(origin, request.method)) {
181-
// @audit - enforce runtime type/input validation! user superstruct from metamask
182183
throw new Error(
183184
`Origin '${origin}' is not allowed to call '${request.method}'`,
184185
);
185186
}
186187

187-
// Handle keyring methods.
188-
return handleKeyringRequest(await getKeyring(), request); // @audit - handleKeyringRequest is async, might req. await? (else returns promise of promise? dblcheck with MM team)
188+
const keyring = await getKeyring();
189+
return handleKeyringRequest(keyring, request);
189190
};
190191

191192
// Improved polling function

packages/snap/src/keyring.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ import type { ICustodianApi } from './lib/types/ICustodianApi';
99
jest.mock('./lib/custodian-types/custodianMetadata', () => ({
1010
custodianMetadata: {
1111
BitGo: {
12-
enabled: false,
12+
production: false,
1313
apiBaseUrl: 'https://mock-url.com',
1414
apiVersion: 'BitGo',
1515
custodianPublishesTransaction: true,
1616
iconUrl: 'https://mock-url.com/icon.svg',
1717
},
1818
ECA3: {
19-
enabled: true,
19+
production: true,
2020
apiBaseUrl: 'https://mock-url.com',
2121
apiVersion: 'ECA3',
2222
custodianPublishesTransaction: false,

packages/snap/src/keyring.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -299,14 +299,18 @@ export class CustodialKeyring implements Keyring {
299299

300300
let deepLink: CustodianDeepLink | null = null;
301301

302+
// Custodians may not support all methods
303+
// but we don't store this anywhere, because they can implement them later
304+
// We rely on the custodian api to throw an error if the deeplink method is not supported
305+
// and generate a default message if that is the case
306+
302307
try {
303308
if (request.request.method === EthMethod.SignTransaction) {
304309
const custodianApi = await this.getCustodianApiForAddress(address);
305310
deepLink = (await custodianApi.getTransactionLink(
306311
custodianId,
307312
)) as CustodianDeepLink;
308313
} else {
309-
// @audit - explicitly check for methods in account config; throw methodNotFound if not exists
310314
const custodianApi = await this.getCustodianApiForAddress(address);
311315
deepLink = (await custodianApi.getSignedMessageLink(
312316
custodianId,
@@ -333,9 +337,7 @@ export class CustodialKeyring implements Keyring {
333337
params: Json,
334338
keyringRequest: KeyringRequest,
335339
): Promise<string> {
336-
switch (
337-
method // @audit input validation
338-
) {
340+
switch (method) {
339341
case EthMethod.PersonalSign: {
340342
const [message, from] = params as [string, string];
341343
const custodianApi = await this.getCustodianApiForAddress(from);

packages/snap/src/lib/custodian-types/custodianMetadata.ts

+22-22
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export type CustodianMetadata = {
66
name: string;
77
legacyName?: string;
88
displayName: string | null;
9-
enabled: boolean | null;
9+
production: boolean | null;
1010
apiVersion: CustodianType;
1111
custodianPublishesTransaction: boolean;
1212
iconUrl: string | null;
@@ -47,7 +47,7 @@ export const custodianMetadata: (
4747
refreshTokenUrl: null,
4848
name: 'bitgo-test',
4949
displayName: 'BitGo Test',
50-
enabled: false,
50+
production: false,
5151
apiBaseUrl: 'https://app.bitgo-test.com/defi/v2',
5252
apiVersion: CustodianType.BitGo,
5353
custodianPublishesTransaction: true,
@@ -62,7 +62,7 @@ export const custodianMetadata: (
6262
name: 'bitgo-prod',
6363
legacyName: 'bitgo',
6464
displayName: 'BitGo',
65-
enabled: true,
65+
production: true,
6666
apiBaseUrl: 'https://app.bitgo.com/defi/v2',
6767
apiVersion: CustodianType.BitGo,
6868
custodianPublishesTransaction: true,
@@ -76,7 +76,7 @@ export const custodianMetadata: (
7676
refreshTokenUrl: null,
7777
name: 'cactus',
7878
displayName: 'Cactus Custody',
79-
enabled: true,
79+
production: true,
8080
apiVersion: CustodianType.Cactus,
8181
custodianPublishesTransaction: true,
8282
iconUrl:
@@ -91,7 +91,7 @@ export const custodianMetadata: (
9191
refreshTokenUrl: 'http://localhost:8090/oauth/token',
9292
name: 'gk8-prod',
9393
displayName: 'GK8 ECA-1',
94-
enabled: true,
94+
production: true,
9595
apiBaseUrl: 'http://localhost:8090',
9696
apiVersion: CustodianType.ECA1,
9797
custodianPublishesTransaction: true,
@@ -104,7 +104,7 @@ export const custodianMetadata: (
104104
refreshTokenUrl: 'http://localhost:8090/oauth/token',
105105
name: 'gk8-eca3-prod',
106106
displayName: 'GK8 ECA-3',
107-
enabled: true,
107+
production: true,
108108
apiBaseUrl: 'http://localhost:8090',
109109
apiVersion: CustodianType.ECA3,
110110
custodianPublishesTransaction: true,
@@ -118,7 +118,7 @@ export const custodianMetadata: (
118118
'https://safe-mmi.staging.gnosisdev.com/api/v1/oauth/token/',
119119
name: 'gnosis-safe-dev',
120120
displayName: 'Safe',
121-
enabled: false,
121+
production: false,
122122
apiBaseUrl: 'https://safe-mmi.staging.gnosisdev.com/api',
123123
apiVersion: CustodianType.ECA1,
124124
custodianPublishesTransaction: true,
@@ -132,7 +132,7 @@ export const custodianMetadata: (
132132
refreshTokenUrl: 'https://safe-mmi.safe.global/api/v1/oauth/token/',
133133
name: 'safe-prod',
134134
displayName: 'Safe',
135-
enabled: true,
135+
production: true,
136136
apiBaseUrl: 'https://safe-mmi.safe.global/api',
137137
apiVersion: CustodianType.ECA1,
138138
custodianPublishesTransaction: true,
@@ -146,7 +146,7 @@ export const custodianMetadata: (
146146
refreshTokenUrl: 'https://safe-mmi.staging.5afe.dev/api/v1/oauth/token/',
147147
name: 'gnosis-safe-staging',
148148
displayName: 'Gnosis Safe Staging',
149-
enabled: false,
149+
production: false,
150150
apiBaseUrl: 'https://safe-mmi.staging.5afe.dev/api',
151151
apiVersion: CustodianType.ECA1,
152152
custodianPublishesTransaction: true,
@@ -161,7 +161,7 @@ export const custodianMetadata: (
161161
'https://saturn-custody.metamask-institutional.io/oauth/token',
162162
name: 'saturn-prod',
163163
displayName: 'Saturn Custody',
164-
enabled: false,
164+
production: false,
165165
apiBaseUrl: 'https://saturn-custody.metamask-institutional.io/eth',
166166
apiVersion: CustodianType.ECA1,
167167
custodianPublishesTransaction: true,
@@ -174,7 +174,7 @@ export const custodianMetadata: (
174174
refreshTokenUrl: 'https://api.mpcvault.com/mmi/token-refresh',
175175
name: 'mpcvault-prod',
176176
displayName: 'MPCVault',
177-
enabled: true,
177+
production: true,
178178
apiBaseUrl: 'https://api.mpcvault.com/mmi',
179179
apiVersion: CustodianType.ECA3,
180180
custodianPublishesTransaction: true,
@@ -189,7 +189,7 @@ export const custodianMetadata: (
189189
'https://neptune-custody.metamask-institutional.io/oauth/token',
190190
name: 'neptune-custody-prod',
191191
displayName: 'Neptune Custody',
192-
enabled: false,
192+
production: false,
193193
apiBaseUrl: 'https://neptune-custody.metamask-institutional.io/eth',
194194
apiVersion: CustodianType.ECA3,
195195
custodianPublishesTransaction: false,
@@ -203,7 +203,7 @@ export const custodianMetadata: (
203203
refreshTokenUrl: 'https://api-preprod.uat.zodia.io/oauth/token',
204204
name: 'zodia-preprod',
205205
displayName: 'Zodia Preprod',
206-
enabled: false,
206+
production: false,
207207
apiBaseUrl: 'https://api-preprod.uat.zodia.io',
208208
apiVersion: CustodianType.ECA1,
209209
custodianPublishesTransaction: true,
@@ -216,7 +216,7 @@ export const custodianMetadata: (
216216
refreshTokenUrl: 'https://mmi.fireblocks.io/v1/auth/access',
217217
name: 'fireblocks-prod',
218218
displayName: 'Fireblocks',
219-
enabled: true,
219+
production: true,
220220
apiBaseUrl: 'https://mmi.fireblocks.io',
221221
apiVersion: CustodianType.ECA1,
222222
custodianPublishesTransaction: true,
@@ -230,7 +230,7 @@ export const custodianMetadata: (
230230
refreshTokenUrl: 'https://zapi.custody.zodia.io/oauth/token',
231231
name: 'zodia-prod',
232232
displayName: 'Zodia',
233-
enabled: true,
233+
production: true,
234234
apiBaseUrl: 'https://zapi.custody.zodia.io',
235235
apiVersion: CustodianType.ECA1,
236236
custodianPublishesTransaction: true,
@@ -243,7 +243,7 @@ export const custodianMetadata: (
243243
refreshTokenUrl: 'https://api.sit.zodia.io/oauth/token',
244244
name: 'zodia-sit',
245245
displayName: 'Zodia SIT',
246-
enabled: false,
246+
production: false,
247247
apiBaseUrl: 'https://api.sit.zodia.io',
248248
apiVersion: CustodianType.ECA1,
249249
custodianPublishesTransaction: true,
@@ -256,7 +256,7 @@ export const custodianMetadata: (
256256
refreshTokenUrl: 'https://api-qa.qa.zodia.io/oauth/token',
257257
name: 'zodia-qa',
258258
displayName: 'Zodia QA',
259-
enabled: false,
259+
production: false,
260260
apiBaseUrl: 'https://api-qa.qa.zodia.io',
261261
apiVersion: CustodianType.ECA1,
262262
custodianPublishesTransaction: true,
@@ -269,7 +269,7 @@ export const custodianMetadata: (
269269
refreshTokenUrl: 'http://localhost:8090/oauth/token',
270270
name: 'gk8-eca3-dev',
271271
displayName: 'GK8',
272-
enabled: false,
272+
production: false,
273273
apiBaseUrl: 'http://localhost:8090',
274274
apiVersion: CustodianType.ECA3,
275275
custodianPublishesTransaction: true,
@@ -282,7 +282,7 @@ export const custodianMetadata: (
282282
refreshTokenUrl: 'https://api.dev.mpcvault.com/mmi/token-refresh',
283283
name: 'mpcvault-dev',
284284
displayName: 'MPCVault',
285-
enabled: false,
285+
production: false,
286286
apiBaseUrl: 'https://api.dev.mpcvault.com/mmi',
287287
apiVersion: CustodianType.ECA3,
288288
custodianPublishesTransaction: false,
@@ -296,7 +296,7 @@ export const custodianMetadata: (
296296
refreshTokenUrl: 'https://gamma.signer.cubist.dev/v0/oauth/token',
297297
name: 'cubist-gamma',
298298
displayName: 'Cubist Gamma',
299-
enabled: false,
299+
production: false,
300300
apiBaseUrl: 'https://gamma.signer.cubist.dev/v0/mmi',
301301
apiVersion: CustodianType.ECA3,
302302
custodianPublishesTransaction: false,
@@ -309,7 +309,7 @@ export const custodianMetadata: (
309309
refreshTokenUrl: 'https://dg5z0qnzb9s65.cloudfront.net/v0/oauth/token',
310310
name: 'cubist-test',
311311
displayName: 'Cubist Test',
312-
enabled: false,
312+
production: false,
313313
apiBaseUrl: 'https://dg5z0qnzb9s65.cloudfront.net/v0/mmi',
314314
apiVersion: CustodianType.ECA3,
315315
custodianPublishesTransaction: false,
@@ -325,7 +325,7 @@ export const custodianMetadata: (
325325
custodianPublishesTransaction: false,
326326
name: 'local-dev',
327327
displayName: 'Local Dev',
328-
enabled: false,
328+
production: false,
329329
iconUrl:
330330
'https://dev.metamask-institutional.io/custodian-icons/neptune-icon.svg',
331331
isManualTokenInputSupported: true,

packages/snap/src/permissions.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ describe('Permissions', () => {
1616
jest.mock('./lib/custodian-types/custodianMetadata', () => ({
1717
custodianMetadata: [
1818
{
19+
production: true,
1920
allowedOnboardingDomains: ['example.com', 'test.com'],
2021
},
2122
],

packages/snap/src/permissions.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,14 @@ originPermissions.set(metamask, metamaskPermissions);
2727
custodianMetadata.forEach((custodian) => {
2828
if (custodian.allowedOnboardingDomains) {
2929
// exclude localhost
30+
31+
if (!config.dev && !custodian.production) {
32+
return;
33+
}
34+
3035
custodian.allowedOnboardingDomains.forEach((domain) => {
31-
// @audit - includes dev endpoints that should be excluded in prod
32-
originPermissions.set(domain, new Set([InternalMethod.Onboard])); // @audit - should enforce HTTPS (this is a trust module; no more insecure transports); check if https prefix, else add it
36+
// Due to a quirk of the snap SDK, we need to allow the onboarding domain as a bare domain
37+
originPermissions.set(domain, new Set([InternalMethod.Onboard]));
3338
originPermissions.set(
3439
`https://${domain}`,
3540
new Set([InternalMethod.Onboard]),
@@ -51,9 +56,9 @@ const localhostPermissions = new Set([
5156
KeyringRpcMethod.GetRequest,
5257
// Custom methods
5358
InternalMethod.Onboard,
54-
InternalMethod.ClearAllRequests, // @audit-ok only local dev
59+
InternalMethod.ClearAllRequests,
5560
]);
5661

5762
if (config.dev) {
58-
originPermissions.set('http://localhost:8000', localhostPermissions); // @audit-ok - remove for prod
63+
originPermissions.set('http://localhost:8000', localhostPermissions);
5964
}

0 commit comments

Comments
 (0)