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
3 changes: 0 additions & 3 deletions eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -1034,9 +1034,6 @@
"packages/solana-wallet-snap/src/core/validation/validators.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 3
},
"@typescript-eslint/only-throw-error": {
"count": 2
}
},
"packages/solana-wallet-snap/src/entities/instructions/instructions.ts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/solana-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": "mmsPn3F/291/s6sb7cq9t9PbNYFCSk26kQ9bIpw54r8=",
"shasum": "5kNtwtBEH5sTzUllGtgXdv0fTfHEdVplRb3DAOgLMd0=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
12 changes: 0 additions & 12 deletions packages/solana-wallet-snap/src/core/validation/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,10 @@ import {
getJsonError,
InvalidParamsError,
SnapError,
UnauthorizedError,
} 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
7 changes: 4 additions & 3 deletions packages/solana-wallet-snap/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { KeyringRpcMethod } from '@metamask/keyring-api';
import { handleKeyringRequest } from '@metamask/keyring-snap-sdk/v2';
import { validateOrigin } from '@metamask/snap-networks-utils';
import { MethodNotFoundError } from '@metamask/snaps-sdk';
import type {
Json,
Expand Down Expand Up @@ -36,10 +37,10 @@ import { onProtocolRequest as onProtocolRequestHandler } from './core/handlers/o
import { handlers as onRpcRequestHandlers } from './core/handlers/onRpcRequest';
import { withCatchAndThrowSnapError } from './core/utils/errors';
import logger from './core/utils/logger';
import { validateOrigin } from './core/validation/validators';
import { eventHandlers as confirmSignInEvents } from './features/confirmation/views/ConfirmSignIn/events';
import { eventHandlers as confirmSignMessageEvents } from './features/confirmation/views/ConfirmSignMessage/events';
import { eventHandlers as confirmSignAndSendTransactionEvents } from './features/confirmation/views/ConfirmTransactionRequest/events';
import { originPermissions } from './permissions';
import { installPolyfills } from './polyfills';
import snapContext, {
clientRequestHandler,
Expand Down Expand Up @@ -70,7 +71,7 @@ export const onRpcRequest: OnRpcRequestHandler = async ({

const { method } = request;

validateOrigin(origin, method);
validateOrigin(origin, method, originPermissions);

const handler = onRpcRequestHandlers[method];

Expand Down Expand Up @@ -105,7 +106,7 @@ export const onKeyringRequest: OnKeyringRequestHandler = async ({
}): Promise<Json> => {
logger.log('[🔑 onKeyringRequest]', request.method, request);

validateOrigin(origin, request.method);
validateOrigin(origin, request.method, originPermissions);

// This is a temporal fix to prevent the swap/bridge functionality breaking
// TODO: Remove this once changes in bridge-status-controller are in place
Expand Down
86 changes: 41 additions & 45 deletions packages/solana-wallet-snap/src/permissions.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,49 @@
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 { ClientRequestMethod } from './core/handlers/onClientRequest';
import { TestDappRpcRequestMethod } from './core/handlers/onRpcRequest/types';
import { ConfigProvider } from './core/services/config/ConfigProvider';

const prodOrigins = ['https://portfolio.metamask.io'];

const config = new ConfigProvider().get();
const isDev = ['local', 'test'].includes(config.environment);

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,
KeyringSnapRpcMethod.SetSelectedAccounts,
// Keyring v1 methods kept for backwards compatibility — callers using
// old method names are still accepted by the permission layer.
KeyringRpcMethod.ListAccounts,
KeyringRpcMethod.CreateAccount,
KeyringRpcMethod.FilterAccountChains,
KeyringRpcMethod.DiscoverAccounts,
KeyringRpcMethod.ListAccountTransactions,
KeyringRpcMethod.ListAccountAssets,
// Methods specific to the test dapp
TestDappRpcRequestMethod.ListWebSockets,
TestDappRpcRequestMethod.ListSubscriptions,
TestDappRpcRequestMethod.TestOnStart,
TestDappRpcRequestMethod.TestOnInstall,
TestDappRpcRequestMethod.TestOnUpdate,
TestDappRpcRequestMethod.SynchronizeAccounts,
TestDappRpcRequestMethod.SetAccountSelected,
TestDappRpcRequestMethod.ConfirmSend,
TestDappRpcRequestMethod.SignRewardsMessage,
])
: new Set([]);
const dappMethods = [
// Keyring v2 methods
KeyringSnapRpcMethod.GetAccounts,
KeyringSnapRpcMethod.GetAccount,
KeyringSnapRpcMethod.DeleteAccount,
KeyringSnapRpcMethod.GetAccountBalances,
KeyringSnapRpcMethod.SubmitRequest,
KeyringSnapRpcMethod.GetAccountTransactions,
KeyringSnapRpcMethod.GetAccountAssets,
KeyringSnapRpcMethod.SetSelectedAccounts,
// Keyring v1 methods kept for backwards compatibility — callers using
// old method names are still accepted by the permission layer.
KeyringRpcMethod.ListAccounts,
KeyringRpcMethod.CreateAccount,
KeyringRpcMethod.FilterAccountChains,
KeyringRpcMethod.DiscoverAccounts,
KeyringRpcMethod.ListAccountTransactions,
KeyringRpcMethod.ListAccountAssets,
// Methods specific to the test dapp
TestDappRpcRequestMethod.ListWebSockets,
TestDappRpcRequestMethod.ListSubscriptions,
TestDappRpcRequestMethod.TestOnStart,
TestDappRpcRequestMethod.TestOnInstall,
TestDappRpcRequestMethod.TestOnUpdate,
TestDappRpcRequestMethod.SynchronizeAccounts,
TestDappRpcRequestMethod.SetAccountSelected,
TestDappRpcRequestMethod.ConfirmSend,
TestDappRpcRequestMethod.SignRewardsMessage,
];

const metamaskPermissions = new Set([
const metamaskMethods = [
// Keyring v2 methods
KeyringSnapRpcMethod.GetAccounts,
KeyringSnapRpcMethod.GetAccount,
Expand All @@ -67,13 +66,10 @@ const metamaskPermissions = new Set([
// Client methods
ClientRequestMethod.SignAndSendTransactionWithoutConfirmation,
ClientRequestMethod.SignProofOfOwnership,
]);

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,
});