Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/tron-wallet-snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/internal-snaps.git"
},
"source": {
"shasum": "JjgAZZwXVK0y4gNHI1erLqSZV5tyn2n5xgbJl7mFT60=",
"shasum": "4Aj/lLoXEU4oXMBNzQBrTD4OHPhklvRQtUl2jFA+Goo=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
10 changes: 4 additions & 6 deletions packages/tron-wallet-snap/src/handlers/keyring/keyring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type {
KeyringSnapRpc,
} from '@metamask/keyring-api/v2';
import { handleKeyringRequest } from '@metamask/keyring-snap-sdk/v2';
import { validateOrigin } from '@metamask/snap-networks-utils';
import type { Logger } from '@metamask/snap-networks-utils';
import {
InvalidParamsError,
Expand All @@ -34,6 +35,7 @@ import { ESSENTIAL_ASSETS } from '../../constants';
import type { Network } from '../../constants';
import { asStrictKeyringAccount } from '../../entities/keyring-account';
import type { TronKeyringAccount } from '../../entities/keyring-account';
import { originPermissions } from '../../permissions';
import type { AccountsService } from '../../services/accounts/AccountsService';
import type { AssetsService } from '../../services/assets/AssetsService';
import type { ConfirmationHandler } from '../../services/confirmation/ConfirmationHandler';
Expand All @@ -54,11 +56,7 @@ import {
UuidStruct,
} from '../../validation/structs';
import type { TronWalletKeyringRequest } from '../../validation/structs';
import {
validateOrigin,
validateRequest,
validateResponse,
} from '../../validation/validators';
import { validateRequest, validateResponse } from '../../validation/validators';
import { BackgroundEventMethod } from '../cronjob/cronjob';
import { TronMultichainMethod } from './keyring-types';

Expand Down Expand Up @@ -104,7 +102,7 @@ export class KeyringHandler implements KeyringSnapRpc {
}

async handle(origin: string, request: JsonRpcRequest): Promise<Json> {
validateOrigin(origin, request.method);
validateOrigin(origin, request.method, originPermissions);
const result = await handleKeyringRequest(this, request);
return result ?? null;
}
Expand Down
5 changes: 3 additions & 2 deletions packages/tron-wallet-snap/src/handlers/rpc/rpc.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { validateOrigin } from '@metamask/snap-networks-utils';
import type { Logger } from '@metamask/snap-networks-utils';
import { MethodNotFoundError } from '@metamask/snaps-sdk';
import type { Json, JsonRpcRequest } from '@metamask/snaps-sdk';

import { validateOrigin } from '../../validation/validators';
import { originPermissions } from '../../permissions';

export class RpcHandler {
readonly #logger: Logger;
Expand All @@ -12,7 +13,7 @@ export class RpcHandler {
}

async handle(origin: string, request: JsonRpcRequest): Promise<Json> {
validateOrigin(origin, request.method);
validateOrigin(origin, request.method, originPermissions);

this.#logger.log('Handling RPC request', request);

Expand Down
25 changes: 25 additions & 0 deletions packages/tron-wallet-snap/src/permissions.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { KeyringSnapRpcMethod } from '@metamask/keyring-api/v2';
import { DEFAULT_METAMASK_ORIGIN } from '@metamask/snap-networks-utils';

import { originPermissions } from './permissions';

// `ENVIRONMENT` differs between local runs (`test`) and CI (`production`), so
// these assertions hold for both permission shapes.
describe('originPermissions', () => {
it('grants MetaMask the privileged keyring methods', () => {
expect(
originPermissions
.get(DEFAULT_METAMASK_ORIGIN)
?.has(KeyringSnapRpcMethod.CreateAccounts),
).toBe(true);
});

it('never grants privileged methods to dapp origins', () => {
const dappMethods = [...originPermissions.entries()]
.filter(([origin]) => origin !== DEFAULT_METAMASK_ORIGIN)
.flatMap(([, methods]) => [...methods]);

expect(dappMethods).not.toContain(KeyringSnapRpcMethod.CreateAccounts);
expect(dappMethods).not.toContain(KeyringSnapRpcMethod.ExportAccount);
});
});
65 changes: 31 additions & 34 deletions packages/tron-wallet-snap/src/permissions.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
import { KeyringRpcMethod } from '@metamask/keyring-api';
import { KeyringSnapRpcMethod } from '@metamask/keyring-api/v2';
import {
createOriginPermissions,
DEFAULT_DEV_ORIGINS,
DEFAULT_PROD_ORIGINS,
} from '@metamask/snap-networks-utils';

import { TestDappRpcRequestMethod } from './handlers/rpc/types';

// eslint-disable-next-line no-restricted-globals
const isDev = process.env.ENVIRONMENT !== 'production';

const prodOrigins = ['https://portfolio.metamask.io'];
const allowedOrigins = isDev ? ['http://localhost:3000'] : prodOrigins;

const dappPermissions = isDev
? new Set([
// Keyring v2 methods
KeyringSnapRpcMethod.GetAccounts,
KeyringSnapRpcMethod.GetAccount,
KeyringSnapRpcMethod.DeleteAccount,
KeyringSnapRpcMethod.GetAccountBalances,
KeyringSnapRpcMethod.SubmitRequest,
KeyringSnapRpcMethod.GetAccountTransactions,
KeyringSnapRpcMethod.GetAccountAssets,
// Keyring v1 methods kept for backwards compatibility — callers using
// old method names are still accepted by the permission layer.
KeyringRpcMethod.ListAccounts,
KeyringRpcMethod.CreateAccount,
KeyringRpcMethod.DiscoverAccounts,
KeyringRpcMethod.ListAccountTransactions,
KeyringRpcMethod.ListAccountAssets,
// Test dapp specific methods
TestDappRpcRequestMethod.ComputeFee,
])
: new Set([]);
const dappMethods = [
// Keyring v2 methods
KeyringSnapRpcMethod.GetAccounts,
KeyringSnapRpcMethod.GetAccount,
KeyringSnapRpcMethod.DeleteAccount,
KeyringSnapRpcMethod.GetAccountBalances,
KeyringSnapRpcMethod.SubmitRequest,
KeyringSnapRpcMethod.GetAccountTransactions,
KeyringSnapRpcMethod.GetAccountAssets,
// Keyring v1 methods kept for backwards compatibility — callers using
// old method names are still accepted by the permission layer.
KeyringRpcMethod.ListAccounts,
KeyringRpcMethod.CreateAccount,
KeyringRpcMethod.DiscoverAccounts,
KeyringRpcMethod.ListAccountTransactions,
KeyringRpcMethod.ListAccountAssets,
// Test dapp specific methods
TestDappRpcRequestMethod.ComputeFee,
];

const metamaskPermissions = new Set([
const metamaskMethods = [
// Keyring v2 methods
KeyringSnapRpcMethod.GetAccounts,
KeyringSnapRpcMethod.GetAccount,
Expand All @@ -51,13 +51,10 @@ const metamaskPermissions = new Set([
KeyringRpcMethod.DiscoverAccounts,
KeyringRpcMethod.ListAccountTransactions,
KeyringRpcMethod.ListAccountAssets,
]);

const metamask = 'metamask';

export const originPermissions = new Map<string, Set<string>>([]);
];

for (const origin of allowedOrigins) {
originPermissions.set(origin, dappPermissions);
}
originPermissions.set(metamask, metamaskPermissions);
export const originPermissions = createOriginPermissions({
dappMethods: isDev ? dappMethods : [],
metamaskMethods,
origins: isDev ? DEFAULT_DEV_ORIGINS : DEFAULT_PROD_ORIGINS,
});
13 changes: 1 addition & 12 deletions packages/tron-wallet-snap/src/validation/validators.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
/* eslint-disable @typescript-eslint/only-throw-error */
import { InvalidParamsError, UnauthorizedError } from '@metamask/snaps-sdk';
import { InvalidParamsError } from '@metamask/snaps-sdk';
import type { Infer, Struct } from '@metamask/superstruct';
import { assert } from '@metamask/superstruct';

import { originPermissions } from '../permissions';

export const validateOrigin = (origin: string, method: string): void => {
if (!origin) {
throw new UnauthorizedError('Origin not found');
}
if (!originPermissions.get(origin)?.has(method)) {
throw new UnauthorizedError('Permission denied');
}
};

/**
* Validates that the request parameters conform to the expected structure defined by the provided struct.
*
Expand Down