1 Executive Summary
This report presents the results of our engagement with MetaMask to review the Gator 7715 Permissions & Kernel Snap.
The review was conducted over 3 calendar weeks, from Aug 11, 2025 to Aug 29, 2025, with a total effort of 4.5 person-weeks, with one reviewer for 3 person-weeks and another with 1.5 person-weeks.
The system enables users to grant time-bound, caveat-restricted permissions for various blockchain operations including ERC-20 token transfers, native token operations, and streaming payments. Through its integration with DeleGator smart accounts and the delegation toolkit, it provides a foundation for automated, user-controlled blockchain interactions while maintaining security through comprehensive validation and user consent mechanisms.
The MetaMask Gator Permissions Snap is an EIP-7715 permissions management system that enables granular control over blockchain permissions through MetaMask’s Snap framework. This dual-snap architecture consists of the Gator Permissions Snap and the Permissions Kernel Snap, working together to implement EIP-7715 for delegated permissions and smart account interactions.
The Permission Kernel Snap implements a registry intended to support multiple 7715-compliant adapters in the future. At present, however, it is hardcoded to the Gator Permission Snap Adapter. While this reduces the kernelβs direct attack surface, it simultaneously increases the systemβs overall exposure, since snap-to-snap communication introduces additional complexity and requires safeguards such as whitelisting, a broker model, and forwarding of the original origin.
The Gator Permission Snap is configured to allow communication from the Kernel Snap (the “router”) and MetaMask internal wallet operations only. The Kernel as the request broker can ask for all offered permissions and request specific permissions requested by a DApp. The adapter also offers a getter to return all issued permissions that can only be accessed by MetaMask.
Update: October 28, 2025 - Mitigations Review
Between October 22, 2025 and October 28, 2025, we conducted a review of the client’s remediation measures implemented in commit 476e653 of the MetaMask/snap-7715-permissions repository.
Update: October 30, 2025 - Additional Mitigations Review
Removed viem dependency with 6da514a.
2 Scope
This review focused on the following repository and code revision:
Third party dependencies packages are out of scope for this review.
The detailed list of files in scope can be found in the Appendix.
2.1 Objectives
Together with client, we identified the following priorities for this review:
- Correctness of the implementation, consistent with the intended functionality and without unintended edge cases.
- Identify vulnerabilities particular to the MetaMask Snaps SDK integration in coherence with the MetaMask Snap Security Guidelines and Threat Model describing a Snap as an extension of the MetaMask Wallet Trust Module.
3 Snap Configuration Overview
As part of the assessment, the following key aspects of the Snap’s configuration were identified:
3.1 EIP-7715 Permissions Kernel Snap
- The Snap serves as a permissions kernel implementing EIP-7715 for managing execution permissions in the MetaMask ecosystem.
- It acts as an intermediary that receives permission requests from DApps and routes them to appropriate permission providers (currently the Gator Permissions Provider Snap).
- The Snap is designed to support multiple permission providers in the future but currently integrates specifically with the
GATOR_PERMISSIONS_PROVIDER_SNAP_ID. - The Snap is state-less and only serves hard-coded adapters from the registry.
Internal Architecture:
- Registry Manager: Manages the permission offer registry and handles finding relevant permissions to grant from available offers.
- RPC Handler: Processes incoming RPC requests and orchestrates the permission granting workflow.
RPC Methods:
wallet_requestExecutionPermissions: The primary method exposed to DApps for requesting execution permissions. This method:- Parses and validates the permission request
- Builds a permission offers registry from the Gator permissions provider
- Finds relevant permissions to grant by filtering against registered offers
- Invokes the permission provider snap to grant attenuated permissions
- Returns the granted permissions to the requesting DApp
Snap Permissions:
snap_dialog: Displays dialogs in the MetaMask UI β οΈendowment:rpc:dapps: true- Allows communication with websites/DAppssnaps: true- Enables communication with other snaps β οΈ
DApp Connectivity and Permissions:
- Connected DApp communicate with the Snap via RPC calls. Any connected DApp can communicate with the Snap. No restrictions or programmatic whitelists.
- Development origins are not explicitly excluded from initial-connections for production builds β οΈ
- The snap allows DApp-to-Snap and Snap-to-Snap. It is unclear if the latter is actually needed β οΈ
State Management:
- No state information is stored or accessed.
Dependencies:
@metamask/snaps-sdk:8.1.0(marked as potential dev dependency)viem:2.31.7β οΈ
Origin Permissions
"initialConnections": {
"local:http://localhost:8082": {},
"npm:@metamask/gator-permissions-snap": {}
},
"initialPermissions": {
"snap_dialog": {},
"endowment:rpc": {
"dapps": true,
"snaps": true
}
- Development origin whitelisted at initialConnections β οΈ
- Trusting
gator-permissions-snapviainitialConnectionsmight not be needed β οΈ
Details
----%<---- raw permissions
π : https://docs.metamask.io/snaps/reference/rpc-api/#wallet_requestsnaps
snap_dialog {}
endowment:rpc { dapps: true, snaps: true }
---->%---- raw permissions
π [snap_dialog]
βοΈ - snap_dialog - Displays a dialog in the MetaMask UI. There are three types of dialogs with different parameters and return types.
β οΈ - this method renders Markdown! check for ctrlchar/markdown/injection
πΈ src/index.ts
π [endowment:rpc]
β- endowment:rpc.dapps - snap can communicate with websites/dapps; check origin for internal api calls!
β οΈ - endowment:rpc.snaps - snap can communicate with other snaps; check origin for internal api calls!
πΈ src/index.ts
π² - Package Dependencies:
- @metamask/snaps-sdk:8.1.0 (πΊ looks like devDependency π)
- viem:2.31.7
[π == Metrics == ]
π 316 (lines of code)
3.2 Gator Permissions Snap
- The Snap serves as a permissions provider implementing EIP-7715 for managing token spending permissions in the MetaMask ecosystem.
- It acts as the core permissions provider that receives permission requests from the EIP-7715 Permissions Kernel Snap and manages the full lifecycle of permission granting, validation, and storage.
- The Snap implements four types of token permissions: ERC-20 Token Stream, ERC-20 Token Periodic, Native Token Stream, and Native Token Periodic.
- The Snap maintains persistent state of granted permissions and provides a management interface for users to view their active permissions.
This is currently the only adapter that Kernel interfaces with.
Internal Architecture:
- Permission Handler Factory: Creates specialized handlers for different permission types with validation rules and UI content generation.
- Permission Request Lifecycle Orchestrator: Manages the complete permission request workflow from validation through user confirmation to delegation creation.
- Confirmation Dialog System: Handles user consent dialogs with dynamic content based on permission type and context.
- Account Controller: Manages EOA account operations and EIP-712 delegation signing for permission enforcement.
- Profile Sync Manager: Persists granted permissions across browser sessions using MetaMask’s profile sync functionality.
- Token Metadata & Pricing Services: Fetches external token information and real-time pricing data for UI display.
RPC Methods:
grantPermission: The primary method for processing permission requests. This method:- Validates incoming permission requests against defined schemas
- Creates appropriate permission handlers based on request type
- Orchestrates user confirmation dialogs showing origin, token details, and permission scope
- Creates EIP-712 delegations for approved permissions
- Stores granted permissions for future reference
getPermissionOffers: Returns available permission types that can be grantedgetGrantedPermissions: Retrieves all previously granted permissions for management purposes
Snap Permissions:
endowment:rpc: Enables communication with other snaps (specifically the EIP-7715 Permissions Kernel) β οΈsnap_manageState: Stores granted permissions and user preferences (up to 100MB isolated storage)endowment:ethereum-provider: Accesses Ethereum API for account operations and delegation signing β οΈendowment:network-access: Makes HTTP requests to external APIs for token metadata and pricing β οΈsnap_dialog: Displays permission confirmation and management dialogs β οΈendowment:lifecycle-hooks: Handles installation and homepage eventssnap_getPreferences: Accesses user preferences for currency and locale settingsendowment:page-home: Provides homepage interface for permission management
DApp Connectivity and Permissions:
- The Snap does not directly communicate with DApps (
dapps: falsein RPC endowment). - All DApp interactions are mediated through the EIP-7715 Permissions Kernel Snap for security isolation.
- Development origins are not explicitly restricted in production builds (manifest), however, they are excluded from the programmatic permission check β οΈ
- The snap allows Snap-to-Snap communication.
npm:@metamask/permissions-kernel-snapis trusted by default.
State Management:
- Persistent storage of granted permissions with origin tracking and expiration management.
- Token metadata caching for improved performance and reduced external API calls.
- User preference synchronization across MetaMask installations via profile sync.
Dependencies:
@metamask/snaps-sdk:8.1.0(Core Snaps functionality)@metamask/delegation-core:0.2.0-rc.1(EIP-712 delegation creation)@metamask/utils:11.4.2(Utility functions for CAIP parsing and validation)viem:2.31.7(Ethereum interactions) β οΈ unusedzod:3.25.76(Runtime validation and type safety)
Origin Permissions
"initialConnections": {
"local:http://localhost:8081": {},
"npm:@metamask/permissions-kernel-snap": {}
},
"initialPermissions": {
"endowment:rpc": {
"dapps": false,
"snaps": true
},
"snap_manageState": {},
"endowment:ethereum-provider": {},
"endowment:network-access": {},
"snap_getEntropy": {},
"snap_dialog": {},
"endowment:lifecycle-hooks": {},
"snap_getPreferences": {},
"endowment:page-home": {}
},
- Development origin whitelisted at initialConnections β οΈ
- Network access enabled for external API calls to token metadata and pricing services β οΈ
- Ethereum provider access for delegation signing and account operations β οΈ
Details
----%<---- raw permissions
π : https://docs.metamask.io/snaps/reference/rpc-api/#wallet_requestsnaps
endowment:rpc { dapps: false, snaps: true }
snap_manageState {}
endowment:ethereum-provider {}
endowment:network-access {}
snap_getEntropy {}
snap_dialog {}
endowment:lifecycle-hooks {}
snap_getPreferences {}
endowment:page-home {}
---->%---- raw permissions
π [endowment:rpc]
β οΈ - endowment:rpc.snaps - snap can communicate with other snaps; check origin for internal api calls!
πΈ src/index.ts
π [snap_manageState]
πͺ€ - snap_manageState - snap can store up to 100mb (isolated)
πΈ src/stateManagement.ts
π [endowment:ethereum-provider]
πΊ - endowment:ethereum-provider - snap can access ethereum API
β οΈ - check if the **snap code** (not site) actually accesses the global 'ethereum' object
see https://docs.metamask.io/snaps/learn/about-snaps/apis/#snap-requests
πΈ src/clients/priceApiClient.ts
π [endowment:network-access]
π - endowment:network-access - snap can access internet
β οΈ - this method may leak information to external api
π [snap_getEntropy]
β¨ - snap_getEntropy - Gets a deterministic 256-bit entropy value, specific to the snap and the user's account. You can use this entropy to generate a private key, or any other value that requires a high level of randomness. Other snaps can't access this entropy, and it changes if the user's secret recovery phrase changes.
πΊ - superfluous permission: no reference to 'snap_getEntropy'!
π [snap_dialog]
βοΈ - snap_dialog - Displays a dialog in the MetaMask UI. There are three types of dialogs with different parameters and return types.
β οΈ - this method renders Markdown! check for ctrlchar/markdown/injection
πΈ src/homepage/index.tsx
πΈ src/core/confirmation.tsx
π [endowment:lifecycle-hooks]
πΊ - endowment:lifecycle-hooks - unknown permission requested
π [snap_getPreferences]
πΊ - snap_getPreferences - unknown permission requested
π [endowment:page-home]
πΊ - endowment:page-home - unknown permission requested
π² - Package Dependencies:
- @metamask/abi-utils:3.0.0 (πΊ looks like devDependency π)
- @metamask/delegation-core:0.2.0-rc.1 (πΊ looks like devDependency π)
- @metamask/delegation-toolkit:0.10.2 (πΊ looks like devDependency π)
- @metamask/profile-sync-controller:21.0.0 (πΊ looks like devDependency π)
- @metamask/snaps-sdk:8.1.0 (πΊ looks like devDependency π)
- @metamask/utils:11.4.2 (πΊ looks like devDependency π)
- viem:2.31.7
- zod:3.25.76
[π == Metrics == ]
...
π 6926 (lines of code)
4 General Findings
Each issue has an assigned severity:
- Critical issues are directly exploitable security vulnerabilities that need to be fixed.
- Major issues are security vulnerabilities that may not be directly exploitable or may require certain conditions in order to be exploited. All major issues should be addressed.
- Medium issues are objective in nature but are not security vulnerabilities. These should be addressed unless there is a clear reason not to.
- Minor issues are subjective in nature. They are typically suggestions around best practices or readability. Code maintainers should use their own judgment as to whether to address such issues.
- Issues without a severity are general recommendations or optional improvements. They are not related to security or correctness and may be addressed at the discretion of the maintainer.
4.1 Remove Debug/Development Origins for Productions Builds Medium ✓ Fixed
Resolution
476e653 by programmatically excluding development hosts from production builds. endowment:lifecycle-hooks is now only available in local dev builds.
Description
It is important to verify that debug/development artefacts and settings are not active in production builds. The MetaMask KeyRing API Security Documentation emphasises the importance of removing all debug code from production snaps.
Examples
- development artefacts (localhost) in manifest
packages/gator-permissions-snap/snap.manifest.json:L20-L23
"initialConnections": {
"local:http://localhost:8081": {},
"npm:@metamask/permissions-kernel-snap": {}
},
packages/permissions-kernel-snap/snap.manifest.json:L20-L22
"initialConnections": {
"local:http://localhost:8082": {},
"npm:@metamask/gator-permissions-snap": {}
Recommendation
Ensure that debug/development configuration and artefacts are not included in production builds. This includes adding dev/debug endpoint permissions only if the environment suggests it’s a debug build. The build scripts should check for the corresponding debug parameterization. This will prevent inadvertent inclusion of debug code in production builds.
4.2 Potential Sensitive Information Disclosure Through Error Logging Minor ✓ Addressed
Resolution
Most instances addressed in MetaMask/snap-7715-permissions@476e653 by not emitting the error object with the logger. The client provided additional details:
Summary of Finding: Detailed logging of errors and requests was observed, posing a risk of sensitive data exposure.
Resolution: Raw logging was replaced with sanitized logging, and all logs were disabled in production builds.
Implementation: PR: MetaMask/snap-7715-permissions#161.
Verification: Production logs were verified to exclude sensitive data (e.g., stack traces, full payloads).
Some instances are left with the logger emitting the error object from a tryCatch statement (mostly logger.error or logger.warn invocations). For example in userEventDispatcher, AccountApiClient, … . However, by default, the loglevel is set to disabled.
Description
Both the kernel and gator snaps log complete error objects and unvalidated request data. This might expose internal and sensitive information like stack traces, API endpoints, and user input to browser logs.
While local attack vectors may not be included in MetaMask’s threat model, it is considered a good practice to avoid exposure of potential sensitive information.
Example
packages/permissions-kernel-snap/src/index.ts:L39-L48
export const onRpcRequest: OnRpcRequestHandler = async ({
origin,
request,
}) => {
logger.info(
`Custom request (origin="${origin}"):`,
JSON.stringify(request, undefined, 2),
);
const handler = boundRpcHandlers[request.method];
packages/permissions-kernel-snap/src/registryManager.ts:L70-L122
async function buildPermissionOffersRegistry(
snapId: string,
): Promise<PermissionOfferRegistry> {
let ephemeralPermissionOfferRegistry: PermissionOfferRegistry = {};
try {
try {
logger.debug(`Querying snap ${snapId} for permission offers...`);
const response = await snapsProvider.request({
method: 'wallet_invokeSnap',
params: {
snapId,
request: {
method: ExternalMethod.PermissionProviderGetPermissionOffers,
},
},
});
if (response) {
const parsedOffers = parsePermissionOffersParam(response);
const uniqueOffersToStore: RegisteredPermissionOffers =
parsedOffers.map((offer) => {
return {
hostId: snapId,
type: offer.type,
proposedName: offer.proposedName,
};
});
ephemeralPermissionOfferRegistry = {
...ephemeralPermissionOfferRegistry,
[snapId]: uniqueOffersToStore,
};
logger.debug(
`Snap ${snapId} supports ${ExternalMethod.PermissionProviderGetPermissionOffers}, adding to registry...`,
);
}
} catch (error) {
logger.error(
{
snapId,
error,
},
`Snap ${snapId} does not support ${ExternalMethod.PermissionProviderGetPermissionOffers}, or returned an invalid response, skipping...`,
);
}
return ephemeralPermissionOfferRegistry;
} catch (error) {
logger.error('Error building permission offer registry:', error);
return ephemeralPermissionOfferRegistry;
}
packages/gator-permissions-snap/src/index.ts:L189-L196
export const onRpcRequest: OnRpcRequestHandler = async ({
origin,
request,
}) => {
logger.debug(
`RPC request (origin="${origin}"):`,
JSON.stringify(request, undefined, 2),
);
packages/gator-permissions-snap/src/services/tokenPricesService.ts:L72-L107
async getCryptoToFiatConversion(
tokenCaip19Type: CaipAssetType,
balance: Hex,
decimals: number,
): Promise<string> {
try {
logger.debug('TokenPricesService:getCryptoToFiatConversion()');
const preferences = await this.#getPreferences();
// Value in fiat=(Amount in crypto)Γ(Spot price)
const tokenSpotPrice = await this.#priceApiClient.getSpotPrice(
tokenCaip19Type,
this.#safeParsePreferences(preferences),
);
const formattedBalance = Number(
formatUnits({ value: BigInt(balance), decimals }),
);
const valueInFiat = formattedBalance * tokenSpotPrice;
const humanReadableValue = formatAsCurrency(preferences, valueInFiat);
logger.debug(
'TokenPricesService:formatAsCurrency() - formatted balance to currency',
humanReadableValue,
);
return humanReadableValue;
} catch (error) {
logger.error(
'TokenPricesService:getCryptoToFiatConversion() - failed to fetch token spot price',
error,
);
// TODO: Return a more user-friendly error message so failed calls to the Price API are handled gracefully
// and do not make the entire permission request fail. We can use cached prices as a fallback to prevent this issue message in UI.
return '$<-->';
}
Please notice similar patterns found in more locations across codebase like: accountApiClient.ts, priceApiClient.ts, tokenMetadataService.ts,blockchainMetadataClient.ts, accountController.ts, …
Recommendation
Given users will likely not act or even notice console logs, consider disabling logging for production builds. Additionally, and in case you don’t want or can’t disable logs for prod, implement an error sanitization utility to remove any sensitive information from logs and use it to replace the raw ones.
5 Findings: Kernel
5.1 Kernel - Prototype Pollution via Method Handler Lookup Major ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by checking Object.prototype.hasOwnProperty on the request struct before accessing it. In Gator this is safeguarded by a check for isMethodAllowedForOrigin. The client provided additional details:
Summary of Finding: request.method lacked validation, enabling prototype pollution.
Resolution: We introduced explicit checks to ensure methods exist directly on the handler object (not on its prototype). Additionally, in gator-permission-snap, we enforce isMethodAllowedForOrigin, which restricts invocation so that only the kernel can call specific methods. This design prevents prototype pollution attacks in that context.
Implementation: PR: MetaMask/snap-7715-permissions#147.
Verification: Attempting to invoke prototype methods correctly fails.
Reviewed call flow in Gator Snap to confirm isMethodAllowedForOrigin ensures untrusted origins cannot bypass validation.
Description
The RPC method handler lookup is vulnerable to prototype pollution attacks. When request.method contains prototype property names like toString, valueOf, constructor, or hasOwnProperty, the code accesses inherited methods from Object.prototype instead of returning undefined. This allows attackers to invoke unintended functions and potentially extract sensitive information or cause unexpected behavior.
Example
boundRpcHandlersinherits functions fromObject.prototype- by accessing
boundRpcHandlers[request.method]without whitelisting method names, the caller can call arbitrary inherited functions
packages/permissions-kernel-snap/src/index.ts:L29-L52
/**
* Handle incoming JSON-RPC requests, sent through `wallet_invokeSnap`.
*
* @param args - The request handler args as object.
* @param args.origin - The origin of the request, e.g., the website that
* invoked the snap.
* @param args.request - A validated JSON-RPC request object.
* @returns The result of `snap_dialog`.
* @throws If the request method is not valid for this snap.
*/
export const onRpcRequest: OnRpcRequestHandler = async ({
origin,
request,
}) => {
logger.info(
`Custom request (origin="${origin}"):`,
JSON.stringify(request, undefined, 2),
);
const handler = boundRpcHandlers[request.method];
if (!handler) {
throw new Error(`Method ${request.method} not found.`);
}
packages/permissions-kernel-snap/src/index.ts:L12-L27
// set up dependencies
const rpcHandler = createRpcHandler({
permissionOfferRegistryManager: createPermissionOfferRegistryManager(snap),
snapsProvider: snap,
});
// configure RPC methods bindings
const boundRpcHandlers: {
[RpcMethod: string]: (options: {
siteOrigin: string;
params?: JsonRpcParams;
}) => Promise<Json>;
} = {
[RpcMethod.WalletRequestExecutionPermissions]:
rpcHandler.requestExecutionPermissions.bind(rpcHandler),
};
Recommendation
Use Object.prototype.hasOwnProperty.call() or Map data structure instead of object property access, or implement explicit method validation using Object.hasOwn() to prevent prototype chain access.
5.2 Kernel - Superfluous Permissions in Manifest Medium ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by removing initialConnections altogether, changing endowment:rpc.snaps = false, and removing the unused snap_dialog.The client provided additional details:
Summary of Finding: Unnecessary permissions (snap_dialog, extra connections) were declared.
Resolution: Remove gatorSnap from the kernel snapβs initialConnections, set the snap field to false for the endowment:rpc permission, and remove the snap_dialog permission from the kernel snap.
Implementation: PRs:
MetaMask/snap-7715-permissions#167
MetaMask/snap-7715-permissions#153
Verification: The manifest was reviewed to confirm adherence to the principle of least privilege.
Description
The permissions kernel snap declares multiple unnecessary permissions in its manifest that violate the principle of least privilege and unnecessarily expand the attack surface. The manifest includes three categories of superfluous permissions:
- The
initialConnectionssection includesnpm:@metamask/gator-permissions-snapdespite the kernel snap never initiating communication with the gator snap. The kernel only processes responses when invoking other snaps. - The
endowment:rpcpermission grants"snaps": trueaccess, but no other snaps initiate communication with the kernel snap. The kernel only handles request-response communications in a unidirectional flow (DApp β Kernel β Gator). - The
snap_dialogpermission is declared but never used in the codebase. All dialog operations are handled by the gator permissions snap.
Example
packages/permissions-kernel-snap/snap.manifest.json:L20-L30
"initialConnections": {
"local:http://localhost:8082": {},
"npm:@metamask/gator-permissions-snap": {}
},
"initialPermissions": {
"snap_dialog": {},
"endowment:rpc": {
"dapps": true,
"snaps": true
}
},
Recommendation
Remove unused npm:@metamask/gator-permissions-snap from initialConnections, set "snaps": false in the RPC endowment configuration and remove snap_dialog to eliminate unnecessary permissions and reduce the potential attack surface.
Also see: Remove Development Artefacts issue 4.1 .
5.3 Kernel - Unused Dependency ‘Viem’ Minor ✓ Fixed
Resolution
Update Oct 30, 2025: The client has removed the import with MetaMask/snap-7715-permissions@6da514a.
Still present in MetaMask/snap-7715-permissions@476e653. 7715-permissions-shared, which is used by both snaps, imports viem but seems to be unused. viem is also imported by site but site references it in code.
The client originally provided the following additional details:
Summary of Finding: The viem dependency was found to be unused.
Resolution: The unused dependency was removed.
Implementation: PR: MetaMask/snap-7715-permissions#154.
Verification: The dependency no longer appears in package.json, and builds successfully complete.
Description
The project declares [email protected] as a dependency but never imports or utilizes this package anywhere in the codebase. This creates unnecessary supply chain exposure and violates security best practices for dependency management.
Example
packages/permissions-kernel-snap/package.json:L49-L52
"dependencies": {
"@metamask/snaps-sdk": "8.1.0",
"viem": "2.31.7"
},
No import statements found in any TypeScript files (src/**/*.ts) or test configurations.
Recommendation
Remove the unused viem dependency from package.json.
5.4 Kernel - onRpcRequest Misleading Function Documentation Minor ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by providing an accurate @returns documentation. The client provided additional details:
Resolution: JSDoc was updated to accurately describe the return type.
Implementation: PR: MetaMask/snap-7715-permissions#160
Verification: Documentation was reviewed, revealing no discrepancies.
Description
The onRpcRequest function documentation contains incorrect information about the return value. The JSDoc comment states that the function “The result of snap_dialog” while the actual implementation returns the result of the 7715 permissions adapter response from boundRpcHandlers.requestExecutionPermissions().
Example
packages/permissions-kernel-snap/src/index.ts:L29-L38
/**
* Handle incoming JSON-RPC requests, sent through `wallet_invokeSnap`.
*
* @param args - The request handler args as object.
* @param args.origin - The origin of the request, e.g., the website that
* invoked the snap.
* @param args.request - A validated JSON-RPC request object.
* @returns The result of `snap_dialog`.
* @throws If the request method is not valid for this snap.
*/
Recommendation
Update the JSDoc documentation to accurately reflect that the function returns the 7715 permissions adapter response, not a snap dialog result.
5.5 Kernel - Recommendation: Enforce Strict Runtime Type & Input Validation Early ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by enforcing input validation on RPC requests early. The client provided additional details:
Resolution: Zod schemas were introduced for validating incoming RPC requests prior to processing.
Implementation: PR: MetaMask/snap-7715-permissions#160.
Verification: Malformed requests are now rejected at an early stage.
Description
The onRpcRequest handler does not validate incoming requests before processing them. The JSDoc mentions it expects a “validated JSON-RPC request object”, but the code should verify if that’s actually happening, rather than directly accessing request.method and request.params without any checks.
The missing validation could enable prototype pollution attacks (see issue 5.1 ) since it does not check request.method in any way before using it as an object key.
Please note request.params gets validated later, but by then it might be too late to prevent method lookup issues.
Example
packages/permissions-kernel-snap/src/index.ts:L29-L60
/**
* Handle incoming JSON-RPC requests, sent through `wallet_invokeSnap`.
*
* @param args - The request handler args as object.
* @param args.origin - The origin of the request, e.g., the website that
* invoked the snap.
* @param args.request - A validated JSON-RPC request object.
* @returns The result of `snap_dialog`.
* @throws If the request method is not valid for this snap.
*/
export const onRpcRequest: OnRpcRequestHandler = async ({
origin,
request,
}) => {
logger.info(
`Custom request (origin="${origin}"):`,
JSON.stringify(request, undefined, 2),
);
const handler = boundRpcHandlers[request.method];
if (!handler) {
throw new Error(`Method ${request.method} not found.`);
}
const result = await handler({
siteOrigin: origin,
params: request.params as JsonRpcParams,
});
return result;
};
The code assumes request.method is a valid string and request.params conforms to JsonRpcParams without any runtime verification.
Recommendation
Implement comprehensive Zod schema validation for all incoming RPC requests before processing.
5.6 Kernel - Inefficient Array Concatenation ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by using array.flat(). The client provided additional details:
Resolution: The reduce method was replaced with Array.prototype.flat().
Implementation: PR: MetaMask/snap-7715-permissions#159.
Verification: Code review confirmed array operations are now efficient and safe.
Description
The getRegisteredPermissionOffers function uses an inefficient O(nΒ²) array concatenation pattern. It is using spread operators inside a reduce, which recreates the entire array on every iteration.
While the current registry is hardcoded to the gator snap, and even considering numerous permissions offers, the risk of causing significant performance degradation or denial of service is reduced, however, it still should be addressed.
Example
packages/permissions-kernel-snap/src/registryManager.ts:L125-L142
/**
* Flattens the permission offer registry into a single array of registered permission offers.
*
* @param permissionOfferRegistry - The permission offer registry to flatten.
* @returns The registered permission offers.
*/
function getRegisteredPermissionOffers(
permissionOfferRegistry: PermissionOfferRegistry,
): RegisteredPermissionOffers {
if (Object.keys(permissionOfferRegistry).length === 0) {
return [];
}
return Object.values(permissionOfferRegistry).reduce(
(acc, offers) => [...acc, ...offers],
[],
);
}
Recommendation
Replace the inefficient reduce pattern with Array.prototype.flat() which operates in O(n) time complexity, or use Array.prototype.concat() for better performance and reduced memory allocation.
6 Findings: Gator
6.1 Gator - Currency Mismatch for Non-English Users Major ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by updating the logic to invoke the Price API with the userβs preferred currency and updating the UI element when falling back to USD. The client provided additional details:
Resolution: Logic was updated to invoke the Price API with the userβs preferred currency, incorporating a fallback mechanism.
Implementation: PR: MetaMask/snap-7715-permissions#152
Verification: Testing across EN, FR, and DE locales confirmed correct currency handling.
Description
A currency mismatch exists in the TokenPricesService implementation that causes non-English users to receive USD price data while displaying it with their local currency formatting. This can potentially create a financial misinformation during permission grant decisions.
The issue occurs in the #safeParsePreferences() method which forces USD currency for all non-English locales when fetching price data, while the formatAsCurrency() function uses the user’s original currency preference for display formatting. This mismatch results in users seeing USD price values formatted with their local currency symbols (EUR, GBP, etc.).
Examples
packages/gator-permissions-snap/src/utils/locale.ts:L11-L14
export const FALLBACK_PREFERENCE: Preferences = {
locale: 'en',
currency: 'USD',
};
packages/gator-permissions-snap/src/services/tokenPricesService.ts:L35-L41
#safeParsePreferences(preferences: Preferences): VsCurrencyParam {
const { currency, locale } = preferences;
return locale === 'en'
? (currency.toLowerCase() as VsCurrencyParam)
: (FALLBACK_PREFERENCE.currency.toLowerCase() as VsCurrencyParam);
}
packages/gator-permissions-snap/src/services/tokenPricesService.ts:L79-L96
const preferences = await this.#getPreferences();
// Value in fiat=(Amount in crypto)Γ(Spot price)
const tokenSpotPrice = await this.#priceApiClient.getSpotPrice(
tokenCaip19Type,
this.#safeParsePreferences(preferences),
);
const formattedBalance = Number(
formatUnits({ value: BigInt(balance), decimals }),
);
const valueInFiat = formattedBalance * tokenSpotPrice;
const humanReadableValue = formatAsCurrency(preferences, valueInFiat);
logger.debug(
'TokenPricesService:formatAsCurrency() - formatted balance to currency',
humanReadableValue,
);
Recommendation
Ensure the Price API is called with the user’s preferred currency when supported, add validation to ensure Price API supports it, and/or add currency conversion logic as a fallback.
Additionally, if the preferred currency is unavailable, it should be clear to the user that the price shown is using a different currency to avoid misinformation.
6.2 Gator - Superfluous Permissions in Manifest Medium ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by removing snap_getEntropy. The client provided additional details:
Resolution: The unused snap_getEntropy permission was removed.
Implementation: PR: MetaMask/snap-7715-permissions#153.
Verification: The manifest was confirmed to align with the principle of least privilege.
Description
The snap manifest declares the snap_getEntropy permission in its initialPermissions section, but analysis of the codebase reveals no usage of entropy generation functionality. The snap_getEntropy permission grants access to cryptographically secure random number generation, which is a sensitive capability that should only be requested when actually needed.
This permission allows the snap to:
- Generate cryptographically secure random values
- Access entropy for cryptographic operations
- Potentially use randomness for security-critical functions
Since the gator-permissions-snap does not utilize entropy generation in its implementation, this permission violates the principle of least privilege by granting unnecessary capabilities that could be exploited if the snap were compromised.
Example
packages/gator-permissions-snap/snap.manifest.json:L32
"snap_getEntropy": {},
Recommendation
Remove the unused snap_getEntropy permission from the initialPermissions configuration to eliminate unnecessary capabilities and reduce the potential attack surface.
Also see: Remove Development Artefacts issue 4.1 .
6.3 Gator - Missing Runtime Verification for API Responses Medium ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by enforcing manual and zod runtime validation via makeValidatedRequestWithRetry for API responses. The client provided additional details:
Resolution: Schema validation using Zod was added for API responses, and request timeouts were enforced.
Implementation: PR: MetaMask/snap-7715-permissions#158
Verification: Invalid or malformed responses are now safely rejected.
Description
The AccountApiClient.getTokenBalanceAndMetadata() method uses a compile time type assertion (await response.json()) as TokenBalanceResponse without validating the actual structure or content of every field in the response at runtime, trusting external API data blindly. Additionally, the method lacks timeout controls, response size limits, and field-level validation.
For example, fields like iconUrl, symbol, and decimals are returned to the caller without sanitization. Additionally, there is no protection against hanging requests that could cause disruptions in MetaMask user experience.
Examples
getTokenBalanceAndMetadata
- decimals: untrusted numeric value
- symbol: untrusted string
- iconUrl: untrusted URL (pot. extension-csrf, tracking) - later used to fetch icon and converted to b64-data-uri
- account: is verified against internal accounts but not ensured to be an array at runtime.
- type: is manually checked
- balance: implicitly via
BigIntconversion
packages/gator-permissions-snap/src/clients/accountApiClient.ts:L102-L119
const response = await this.#fetch(
`${this.#baseUrl}/tokens/${tokenAddress}?accountAddresses=${account}&chainId=${chainId}`,
);
if (!response.ok) {
const message = `HTTP error. Failed to fetch token balance for account(${account}) and token(${tokenAddress}) on chain(${chainId}): ${response.status}`;
logger.error(message);
throw new Error(message);
}
const { accounts, type, iconUrl, symbol, decimals } =
(await response.json()) as TokenBalanceResponse;
const accountLowercase = account.toLowerCase();
const accountData = accounts.find(
(acc) => acc.accountAddress.toLowerCase() === accountLowercase,
);
getSpotPrice - missing runtime type enforcement
packages/gator-permissions-snap/src/clients/priceApiClient.ts:L40-L76
const response = await this.#fetch(
`${
this.#baseUrl
}/v3/spot-prices?includeMarketData=false&vsCurrency=${vsCurrency}&assetIds=${caipAssetType}`,
);
if (!response.ok) {
logger.error(
`HTTP error! Failed to fetch spot price for caipAssetType(${caipAssetType}) and vsCurrency(${vsCurrency}): ${response.status}`,
);
throw new Error(
`HTTP error! Failed to fetch spot price for caipAssetType(${caipAssetType}) and vsCurrency(${vsCurrency}): ${response.status}`,
);
}
const spotPricesRes = (await response.json()) as SpotPricesRes;
const assetTypeData = spotPricesRes[caipAssetType];
if (!assetTypeData) {
logger.error(
`No spot price found in result for the token CAIP-19 asset type: ${caipAssetType}`,
);
throw new Error(
`No spot price found in result for the token CAIP-19 asset type: ${caipAssetType}`,
);
}
const vsCurrencyData = assetTypeData[vsCurrency];
if (!vsCurrencyData) {
logger.error(
`No spot price found in result for the currency: ${vsCurrency}`,
);
throw new Error(
`No spot price found in result for the currency: ${vsCurrency}`,
);
}
return vsCurrencyData;
Recommendation
- Add request timeout controls to prevent hanging requests.
- Implement runtime JSON schema validation via zod instead of relying on type assertions.
6.4 Gator - Missing Runtime Schema Verification for Profile Sync Store/Retrieve Medium ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by enforcing zod validation on profile sync read and writes. The client provided additional details:
Resolution: Runtime schema validation and size limits were implemented for stored permission data.
Implementation: PR: MetaMask/snap-7715-permissions#157
Verification: Invalid JSON now fails validation and is rejected.
Description
The Profile Sync performs unsafe deserialization of permission data without runtime schema validation.
JSON.parseonly validates JSON syntax, not data structure- The type assertion
as StoredGrantedPermissionis a compile-time hint only - At runtime, there’s no guarantee the parsed object matches the expected structure
The code comments explicitly state that βit is up to the SDK consumer to enforce proper schema managementβ (lines 147β149). However, no such validation is implemented. Because profile sync data is shared across devices, erroneous or malicious data could propagate and impact all connected devices.
Examples
packages/gator-permissions-snap/src/profileSync/profileSync.ts:L99-L118
/**
* Retrieve all granted permission items under the "7715_permissions" feature will result in GET /api/v1/userstorage/7715_permissions
* VALUES: decrypted("JSONstringifyPermission1", storage_key), decrypted("JSONstringifyPermission2", storage_key).
* @returns All granted permissions.
*/
async function getAllGrantedPermissions(): Promise<
StoredGrantedPermission[]
> {
try {
await authenticate();
const items = await userStorage.getAllFeatureItems(FEATURE);
return (
items?.map((item) => JSON.parse(item) as StoredGrantedPermission) ?? []
);
} catch (error) {
logger.error('Error fetching all granted permissions:', error);
throw error;
}
}
packages/gator-permissions-snap/src/profileSync/profileSync.ts:L126-L141
async function getGrantedPermission(
permissionContext: Hex,
): Promise<StoredGrantedPermission | null> {
try {
await authenticate();
const path: UserStorageGenericPathWithFeatureAndKey = `${FEATURE}.${generateObjectKey(permissionContext)}`;
const permission = await userStorage.getItem(path);
return permission
? (JSON.parse(permission) as StoredGrantedPermission)
: null;
} catch (error) {
logger.error('Error fetching granted permissions:', error);
throw error;
}
setter should prevent the storage of non conformant structures
packages/gator-permissions-snap/src/profileSync/profileSync.ts:L144-L166
/**
* Store the granted permission in profile sync.
*
* Persisting "<permissionContext>" key under "gator_7715_permissions" feature
* value has to be serialized to string and does not exceed 400kb
* it is up to the SDK consumer to enforce proper schema management
* will result in PUT /api/v1/userstorage/gator_7715_permissions/Hash(<storage_key+<permissionContext>">)
* VALUE: encrypted("JSONstringifyPermission", storage_key).
* @param storedGrantedPermission - The permission response to store.
*/
async function storeGrantedPermission(
storedGrantedPermission: StoredGrantedPermission,
): Promise<void> {
try {
await authenticate();
const path: UserStorageGenericPathWithFeatureAndKey = `${FEATURE}.${generateObjectKey(storedGrantedPermission.permissionResponse.context)}`;
await userStorage.setItem(path, JSON.stringify(storedGrantedPermission));
} catch (error) {
logger.error('Error storing granted permission:', error);
throw error;
}
}
Recommendation
Implement runtime schema validation using Zod for all stored permission data.
Add size validation before storage to enforce the documented 400kb limit and handle validation errors gracefully to prevent crashes from corrupted data.
6.5 Gator - Inconsistent Atomicity Expectation in Batch Permission Grants Minor ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by first checking all permissions for approvals and only storing them, when the complete batch is approved. The client provided additional details:
Resolution: Updated the implementation to ensure permission requests are processed sequentially. Storage is only updated once all permissions have been successfully processed, guaranteeing atomicity.
Implementation: PR: MetaMask/snap-7715-permissions#150
Verification: Partial failures were confirmed to no longer result in orphaned permissions.
Description
The batch permission handling in grantPermission introduces a critical atomicity flaw. When processing multiple permissions, successful grants are written to ProfileSync but are never reported back to the requesting dApp if any subsequent grant fails. Because Promise.all aborts on the first rejection, earlier successful operations remain committed while the overall request is returned as a failure.
This results in orphaned permissions: permissions that exist in the system but are unknown to the client. Such partial success weakens transactional integrity, leading to semi-consistent state, potential permission confusion, and corrupted audit trails. Since partial permissions are not returned the severity was estimated as Minor.
Example
A batch request [A, B, C]:
AandBsucceed and are stored.Cfails.- The dApp receives a total failure response, but
AandBremain silently stored in ProfileSync.
// Batch request: [Permission A, Permission B, Permission C]
// Execution flow:
// 1. Permission A: β
Signed β β
Stored β β
Success
// 2. Permission B: β
Signed β β
Stored β β
Success
// 3. Permission C: β
Signed β β Storage Fails β π₯ Promise.all REJECTS
// Result: Permissions A & B are stored but NEVER returned to dApp
// Impact: Orphaned permissions in storage, inconsistent dApp state
packages/gator-permissions-snap/src/rpc/rpcHandler.ts:L50-L84
/**
* Handles grant permission requests.
*
* @param params - The parameters for the grant permission request.
* @returns The result of the grant permission request.
*/
const grantPermission = async (params?: Json): Promise<Json> => {
logger.debug('grantPermissions()', params);
const { permissionsRequest, siteOrigin } =
validatePermissionRequestParam(params);
const responses = await Promise.all(
permissionsRequest.map(async (request) => {
const handler =
permissionHandlerFactory.createPermissionHandler(request);
const permissionResponse =
await handler.handlePermissionRequest(siteOrigin);
if (!permissionResponse.approved) {
throw new Error(permissionResponse.reason);
}
if (permissionResponse.response) {
await profileSyncManager.storeGrantedPermission({
permissionResponse: permissionResponse.response,
siteOrigin,
});
}
return permissionResponse.response;
}),
);
return responses as Json[];
Recommendation
Adopt a transaction-safe approach:
- Use a two-phase commit with pending and confirmed states, or
- Replace
Promise.allwithPromise.allSettledand introduce cleanup logic to roll back partial grants, or - have ProfileSync provide a transaction wrapper.
6.6 Gator - Lifecycle Hooks Permission Used Primarily for Development Features ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by only including endowment:lifecycle-hooks when snapEnv === 'local'. The client provided additional details:
Resolution: endowment:lifecycle-hooks was removed from production builds.
Implementation: PR: MetaMask/snap-7715-permissions#164.
Verification: The manifest was reviewed to confirm its removal.
Description
The endowment:lifecycle-hooks permission is requested but the onInstall handler primarily serves development purposes, with minimal production functionality (welcome screen). This expands the attack surface for limited production benefit and violates the principle of least privilege.
- Development-only logic (lines 243-254): Conditional installation of the message signing snap only in local development mode
- Minimal production functionality (line 258): Only shows a welcome screen
The development logic is gated behind environment conditions (snapEnv === 'local' && isStorePermissionsFeatureEnabled), meaning that in production builds, the lifecycle hook primarily serves to display a welcome screen - functionality that could be handled through other means.
Example
packages/gator-permissions-snap/src/index.ts:L232-L259
export const onInstall: OnInstallHandler = async () => {
/**
* Local Development Only
*
* The message signing snap must be installed and the gator permissions snap must
* have permission to communicate with the message signing snap, or the request is rejected.
*
* Since the message signing snap is preinstalled in production, and has
* initialConnections configured to automatically connect to the gator snap, this is not needed in production.
*/
// eslint-disable-next-line no-restricted-globals
if (snapEnv === 'local' && isStorePermissionsFeatureEnabled) {
const installedSnaps = (await snap.request({
method: 'wallet_getSnaps',
})) as unknown as GetSnapsResponse;
if (!installedSnaps[MESSAGE_SIGNING_SNAP_ID]) {
logger.debug('Installing local message signing snap');
await snap.request({
method: 'wallet_requestSnaps',
params: {
[MESSAGE_SIGNING_SNAP_ID]: {},
},
});
}
}
await homepage.showWelcomeScreen();
};
Recommendation
Consider removing the endowment:lifecycle-hooks permission for production builds since:
6.7 Gator - Misleading Debug Message ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by changing the debug message text. The client provided additional details:
Resolution: The debug log message in getNonce() was corrected.
Implementation: PR: MetaMask/snap-7715-permissions#156.
Verification: Logs now accurately reflect the function name.
Description
The function is getNonce and the debug log prints BlockchainTokenMetadataClient:getTokenBalanceAndMetadata().
packages/gator-permissions-snap/src/clients/nonceCaveatClient.ts:L33-L46
public async getNonce({
chainId,
account,
}: {
chainId: number;
account: Hex;
}): Promise<bigint> {
logger.debug('BlockchainTokenMetadataClient:getTokenBalanceAndMetadata()');
if (!chainId) {
const message = 'No chainId provided to fetch nonce';
logger.error(message);
throw new Error(message);
}
Recommendation
Fix debug message.
6.8 Gator - Recommendation: TokenIcon SVG Runtime Type Enforcement ✓ Fixed
Resolution
Fixed in MetaMask/snap-7715-permissions@476e653 by enforcing zod schema input validation on the caller provided parameters. The client provided additional details:
Resolution: Runtime type checks were added for SVG inputs (base64 data URI, width, height).
Implementation: PR: MetaMask/snap-7715-permissions#155
Verification: Malformed inputs are rejected at runtime.
Description
The TokenIcon SVG image is generated through string concatenation, which poses a potential risk of HTML injection. The imageβs width and height are not enforced at runtime and may deviate from their compile-time type declarations. Although we did not identify any instances where this issue is directly exploitable, we strongly recommend implementing runtime type checks and format validations to mitigate potential risks.
- base64 data uri is always in data uri format when passed by callers. however the function does not enforce it.
- width/height are never passed to TokenIcon and defaults to numeric 24 (px).
Also, the SVG is rendered within an <img> tag, which prevents JavaScript or interaction events from being supported. Nevertheless, the inputs should be strictly validated to reduce attack surface.
Examples
packages/gator-permissions-snap/src/ui/components/TokenIcon.tsx:L11-L23
export const TokenIcon: SnapComponent<TokenIconParams> = ({
imageDataBase64,
altText,
width = 24,
height = 24,
}) => {
if (!imageDataBase64) {
return <Text> </Text>;
}
const imageSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<image href="${imageDataBase64}" width="${width}" height="${height}" />
</svg>`;
7 Document Change Log
| Version | Date | Description |
|---|---|---|
| 1.0 | 2025-08-20 | Initial report |
| 1.1 | 2025-10-28 | Mitigations review: MetaMask/snap-7715-permissions@476e653 |
| 1.2 | 2025-10-30 | Mitigations review: MetaMask/snap-7715-permissions@6da514a |
Appendix 1 - Files in Scope
This review covered the following files:
| File | SHA-1 hash |
|---|---|
| LICENSE.APACHE2 | 7c8c3d0d057417da25b92823c1075d9b4297af55 |
| LICENSE.MIT0 | 8ac914386a5bf48bbf57f0289773e24ba5c36086 |
| packages/gator-permissions-snap/images/icon.svg | 747c68b49c159aa4e320b76cfe1d086f798da24f |
| packages/gator-permissions-snap/images/toggle_disabled.svg | 08661c273c3fb0d1065b4a5cd1f3623c1f9c0e15 |
| packages/gator-permissions-snap/images/toggle_enabled.svg | 701275f64fa8951268584704f787c7d0e17aca83 |
| packages/gator-permissions-snap/jest.config.js | a39ea3b638dfc3ee88ffd03da53523107c325a30 |
| packages/gator-permissions-snap/jest.setup.ts | bbee55256035e8e23710822bd96921cb52eeb3d1 |
| packages/gator-permissions-snap/scripts/build-preinstalled-snap.js | c7486810f94aefbf0c8cdf08d8c9ce1711ff157b |
| packages/gator-permissions-snap/snap.config.ts | a8dc0f2e03e43cfe6690118c98618456789f71f8 |
| packages/gator-permissions-snap/src/clients/accountApiClient.ts | 267479513f5a3b52ff8cba1b7ca71d08d3fec6ce |
| packages/gator-permissions-snap/src/clients/blockchainMetadataClient.ts | 15c616a9da116bfaea627f77a1bad64e96596b4a |
| packages/gator-permissions-snap/src/clients/nonceCaveatClient.ts | b938be986102b867d2ae1778285d92f683ee283c |
| packages/gator-permissions-snap/src/clients/priceApiClient.ts | 614c23b307679e6d877a83b2c4bec561ffb93fe2 |
| packages/gator-permissions-snap/src/clients/types.ts | ffaaefcf6ed0938bca198e59d5037b7dab088363 |
| packages/gator-permissions-snap/src/constants.ts | 9f6143eefc5a922d96e846602b95879908789610 |
| packages/gator-permissions-snap/src/core/accountController.ts | 000c53d85ee1621c24fbbc6da1e51be898df732a |
| packages/gator-permissions-snap/src/core/chainMetadata.ts | 3154803c5f6a8b76bf172bb6e738c844c683d106 |
| packages/gator-permissions-snap/src/core/confirmation.tsx | b3912e984d125e5698c1a1aa9b21b236d41696ce |
| packages/gator-permissions-snap/src/core/confirmationFactory.ts | 219271b36986f9e4cc15285e3565d1664f352357 |
| packages/gator-permissions-snap/src/core/permissionHandler.ts | 22c1ceb774766fa539cfb0c3a2fa7c5b7c507298 |
| packages/gator-permissions-snap/src/core/permissionHandlerContent.tsx | 12b97c1fe502ee276748a09308cd36e24f9ff3e3 |
| packages/gator-permissions-snap/src/core/permissionHandlerFactory.ts | 27328f3f8e7a9543ad783174cb8dcf8b014df3a2 |
| packages/gator-permissions-snap/src/core/permissionRequestLifecycleOrchestrator.ts | f868563d74e78c78afd205e0a16b108a9118ce74 |
| packages/gator-permissions-snap/src/core/rules.tsx | 49598b8eb8f1a1b757a5072bf2737cdc14407e9a |
| packages/gator-permissions-snap/src/core/types.ts | ee73f9016f324e86f0ccf94840ffd6ef1a4174f4 |
| packages/gator-permissions-snap/src/homepage/index.tsx | a4ea60d11f4ef406b71f72786d4389c59b9ce49b |
| packages/gator-permissions-snap/src/index.ts | 0f20db943b3f498602a9289b919bbf4d3159d6e1 |
| packages/gator-permissions-snap/src/permissions/contextValidation.ts | da927c5d8417245d9e0a7f9f9f3824a57ac1214a |
| packages/gator-permissions-snap/src/permissions/erc20TokenPeriodic/caveats.ts | 3e580ebc593126b9a0c7a95d1eec6297e28319b4 |
| packages/gator-permissions-snap/src/permissions/erc20TokenPeriodic/content.tsx | 27b427d995101c6d564e2a5b581b29779ba6355a |
| packages/gator-permissions-snap/src/permissions/erc20TokenPeriodic/context.ts | a11a4adccdc7ca42cf341661cb051447d8ec3309 |
| packages/gator-permissions-snap/src/permissions/erc20TokenPeriodic/index.ts | 5d3f5087d7f8da91cc24a4de2fb7fccb71abe8f3 |
| packages/gator-permissions-snap/src/permissions/erc20TokenPeriodic/rules.ts | c7c863a7c98a6ec1518980c614df92a1c227e451 |
| packages/gator-permissions-snap/src/permissions/erc20TokenPeriodic/types.ts | 20418570e8fcee337d114ec9018ca9e9ab38c0af |
| packages/gator-permissions-snap/src/permissions/erc20TokenPeriodic/validation.ts | 444f35ef86b13eb3936351bf974e66837e505851 |
| packages/gator-permissions-snap/src/permissions/erc20TokenStream/caveats.ts | a033d141d9c640a49524bd095dd0770a81272ada |
| packages/gator-permissions-snap/src/permissions/erc20TokenStream/content.tsx | f6c1e33326fca2399c06a9421413fa52ebf1b74b |
| packages/gator-permissions-snap/src/permissions/erc20TokenStream/context.ts | 78265977f7421505993971399a6e7bd4b905e92e |
| packages/gator-permissions-snap/src/permissions/erc20TokenStream/index.ts | 4fae5c9c01e8b67b795be12c398742ad51b43ddd |
| packages/gator-permissions-snap/src/permissions/erc20TokenStream/rules.ts | dcdb0284f24dcc714f547d099f0c5787d8bb2058 |
| packages/gator-permissions-snap/src/permissions/erc20TokenStream/types.ts | 0d4f331525cbc4620fd342289830bdc4e39fb586 |
| packages/gator-permissions-snap/src/permissions/erc20TokenStream/validation.ts | a46c889cef8def3d0c38a81632f3bb0c01a8e769 |
| packages/gator-permissions-snap/src/permissions/iconUtil.ts | 779b305201bf0508da53d586d48066539e797156 |
| packages/gator-permissions-snap/src/permissions/nativeTokenPeriodic/caveats.ts | 0a99b0219571fc689351692abeff69e388a08eaf |
| packages/gator-permissions-snap/src/permissions/nativeTokenPeriodic/content.tsx | 47cf7be8e020da538327640f6636bfac7ab05b92 |
| packages/gator-permissions-snap/src/permissions/nativeTokenPeriodic/context.ts | 4570cbe0f93d87ee97dfdd4bd8b6c5018e22d7b5 |
| packages/gator-permissions-snap/src/permissions/nativeTokenPeriodic/index.ts | 5e29e4203477a0d73a53809d2fe4edbed8c1b3fd |
| packages/gator-permissions-snap/src/permissions/nativeTokenPeriodic/rules.ts | 587cec294c818bbb439fb193224e6b19aaf6cdbc |
| packages/gator-permissions-snap/src/permissions/nativeTokenPeriodic/types.ts | 98b2678cd0ce5fdd515cc212b02739115bbf36f0 |
| packages/gator-permissions-snap/src/permissions/nativeTokenPeriodic/validation.ts | 2d2525d19116559f318fab21d4689ccbaae8355f |
| packages/gator-permissions-snap/src/permissions/nativeTokenStream/caveats.ts | 46051eed07543ed15cd1f2602628dadf471e453a |
| packages/gator-permissions-snap/src/permissions/nativeTokenStream/content.tsx | f37d2726beeeac75966081a54423b590f2d3ba50 |
| packages/gator-permissions-snap/src/permissions/nativeTokenStream/context.ts | ac43e0db5c57c09861dd42e85db16760a6fd1a15 |
| packages/gator-permissions-snap/src/permissions/nativeTokenStream/index.ts | 2120ed1ac42791fa02118f4be8e3a65932924267 |
| packages/gator-permissions-snap/src/permissions/nativeTokenStream/rules.ts | e3dd06fc4d205be1e3b691bc85ca4c9ffb661ab5 |
| packages/gator-permissions-snap/src/permissions/nativeTokenStream/types.ts | b710b7ddca846675c379291ef44ac320703fa173 |
| packages/gator-permissions-snap/src/permissions/nativeTokenStream/validation.ts | 5fd7bf937abffd9ce3eb0e4f60e116c5f6f8439a |
| packages/gator-permissions-snap/src/permissions/permissionOffers.ts | aec3b051220d3c9a75721b9460adaf7182dab39e |
| packages/gator-permissions-snap/src/permissions/validation.ts | dac746182cf8d86d0ded2af2ff1d9e65c2c2dcc1 |
| packages/gator-permissions-snap/src/profileSync/config.ts | 9b64c57db0b347ff0196df5b28320dc3c830759c |
| packages/gator-permissions-snap/src/profileSync/index.ts | 7d95e45f69db1ccdacd6243960db385147e4f2df |
| packages/gator-permissions-snap/src/profileSync/options.ts | 29505f2c36567d0aaeb6208e486f7406c2e1f960 |
| packages/gator-permissions-snap/src/profileSync/profileSync.ts | f946be64cb28cf86f098e3be4cf0bf942180c539 |
| packages/gator-permissions-snap/src/rpc/permissions.ts | 359f9762a300dd59b69a15ccc37dcbd233c8c128 |
| packages/gator-permissions-snap/src/rpc/rpcHandler.ts | d7a96554058e1e4a77276f78e899add341040bb6 |
| packages/gator-permissions-snap/src/rpc/rpcMethod.ts | c009720b95652254bae6dd44d76e147753e12f61 |
| packages/gator-permissions-snap/src/services/nonceCaveatService.ts | 3cb3498b1a1d16924c11335e0c49e7b0eecd30a4 |
| packages/gator-permissions-snap/src/services/tokenMetadataService.ts | 79383d014f03b0627608697f090a8fdfde7c05b7 |
| packages/gator-permissions-snap/src/services/tokenPricesService.ts | f813297fb008c5da179ca4e8d7e2b97ee7dface2 |
| packages/gator-permissions-snap/src/stateManagement.ts | 79007573da3258ef15acf5259f4a939c5995efee |
| packages/gator-permissions-snap/src/ui/components/DateTimeField.tsx | b8076baf0b113f39657ea512a2b4745ada3f651a |
| packages/gator-permissions-snap/src/ui/components/DropdownField.tsx | b7fd79cfe93c00c833b41208aed12421755533c0 |
| packages/gator-permissions-snap/src/ui/components/Field.tsx | 9c2d2a76f4d8b5a8b690780c0bcba18898426fc2 |
| packages/gator-permissions-snap/src/ui/components/InputField.tsx | 25837e2cebcf90a53cc0f5f7a344c12bc0af1743 |
| packages/gator-permissions-snap/src/ui/components/ShowMoreText.tsx | f81a639e1f3d7c2e46e85fe45f32170730a03d08 |
| packages/gator-permissions-snap/src/ui/components/SkeletonField.tsx | f79b9f2c62bb93995ca06f73da73c60a09e64ac7 |
| packages/gator-permissions-snap/src/ui/components/TextField.tsx | 3f7d62f5f85b85f92795195a7d1fda0619551304 |
| packages/gator-permissions-snap/src/ui/components/TokenField.tsx | 76d72636ecb2fd163fc708e83f9cc10608143c09 |
| packages/gator-permissions-snap/src/ui/components/TokenIcon.tsx | 231be99e9d0cd83b8ec4a295a7836813e7cf5d3f |
| packages/gator-permissions-snap/src/ui/components/TooltipIcon.tsx | 0edbe761a8aebbf2fff3b3e1805203bba1b7c569 |
| packages/gator-permissions-snap/src/ui/components/index.ts | 1e7f4089b501a604c811ed49bce0504f0723c90d |
| packages/gator-permissions-snap/src/userEventDispatcher.ts | b2ea29722fecda25916749a37bf605e6d6d13b6b |
| packages/gator-permissions-snap/src/utils/locale.ts | 867998bcfcbaa5eb79d9586bddf8971023a6c3ee |
| packages/gator-permissions-snap/src/utils/string.ts | 2f91bb16e9414c11ff128a69139fe5b9045b1b5b |
| packages/gator-permissions-snap/src/utils/time.ts | 57587b36ee311a48ec5c9e1a8fd2a26dbba33ef3 |
| packages/gator-permissions-snap/src/utils/validate.ts | 2d1858c0d61160369ec61d71c632430e53b16ec6 |
| packages/gator-permissions-snap/src/utils/value.ts | 86317060f35d107b0d635834bcd85ff7e5618ce7 |
| packages/gator-permissions-snap/svg-transformer.js | 36626851f55d008bf32a6a56697d89e566e0762e |
| packages/permissions-kernel-snap/images/icon.svg | 747c68b49c159aa4e320b76cfe1d086f798da24f |
| packages/permissions-kernel-snap/jest.config.js | d76b4c37b6a3673a45a454ba99f8e4731ee5adfd |
| packages/permissions-kernel-snap/jest.setup.ts | bbee55256035e8e23710822bd96921cb52eeb3d1 |
| packages/permissions-kernel-snap/scripts/build-preinstalled-snap.js | 1d09b4da1d58fc1ab1cacb0f9e5e7bd7c3c01733 |
| packages/permissions-kernel-snap/snap.config.ts | 1a05bb79e1bcba834a3fac4cb1901ab591f80542 |
| packages/permissions-kernel-snap/src/index.ts | 237446a92c4fc9854d1254da6dc176bd94c75455 |
| packages/permissions-kernel-snap/src/registryManager.ts | 50f5ab94e15db40b63ee716b3186b00b3c7ae345 |
| packages/permissions-kernel-snap/src/rpc/rpcHandler.ts | 2826b12d6f4ee93c14fce1a6736e1eac5465f2a6 |
| packages/permissions-kernel-snap/src/rpc/rpcMethod.ts | 83699d8982c18bd66c0f3e3a0153bb973cf6994e |
| packages/permissions-kernel-snap/src/utils/error.ts | 87671ab801b32df74000cd4f7a505c5328c9940f |
| packages/permissions-kernel-snap/src/utils/index.ts | 8d5ec6b8918c0c3532e51237a89a54dbd12228d0 |
| packages/permissions-kernel-snap/src/utils/validate.ts | d51fa025396afc4352db584b22621cf273b17371 |
| packages/shared/jest.config.js | 2c7fbd0b105504e3de2afda34842356d68b04c48 |
| packages/shared/src/constants/index.ts | 4c674df45ba5501d0de3e4d7a7d3f9caf5c0aaa7 |
| packages/shared/src/types/7715-permissions-request.ts | c2273df9528a3b839eeccce3a0797ccf61411c07 |
| packages/shared/src/types/7715-permissions-response.ts | d507e914fa723dc9dd1dd421f52bf052e3e5e0cc |
| packages/shared/src/types/7715-permissions-types.ts | 20e1d31454ee988e25805e085484c5d5600e3f59 |
| packages/shared/src/types/common.ts | b9bef1f6d457606dd2646d99294429c7040342b7 |
| packages/shared/src/types/index.ts | ea43b5ad0e4ef08bd813fd47ac55539ad8248d30 |
| packages/shared/src/types/snap-permission-registry.ts | c1040dca93ae4bed9013d3400c4bef1391c93b43 |
| packages/shared/src/types/snap.ts | 53458a1caced5d72c1b4fd480dc5ed72238f763c |
| packages/shared/src/utils/common.ts | f8d42802679d48307ac9b0529adf6767edea37b0 |
| packages/shared/src/utils/error.ts | 6eee9d3e7d525e570c07a7de8eaa6bd3463ffdb5 |
| packages/shared/src/utils/index.ts | b99980208c35ab16669225346a38bf7b539253a7 |
| packages/shared/src/utils/logger.ts | bce3117d83080b7e727232ee195febde9cb0119b |
Appendix 2 - Disclosure
Consensys Diligence (“CD”) typically receives compensation from one or more clients (the “Clients”) for performing the analysis contained in these reports (the “Reports”). The Reports may be distributed through other means, including via Consensys publications and other distributions.
The Reports are not an endorsement or indictment of any particular project or team, and the Reports do not guarantee the security of any particular project. This Report does not consider, and should not be interpreted as considering or having any bearing on, the potential economics of a token, token sale or any other product, service or other asset. Cryptographic tokens are emergent technologies and carry with them high levels of technical risk and uncertainty. No Report provides any warranty or representation to any third party in any respect, including regarding the bug-free nature of code, the business model or proprietors of any such business model, and the legal compliance of any such business. No third party should rely on the Reports in any way, including for the purpose of making any decisions to buy or sell any token, product, service or other asset. Specifically, for the avoidance of doubt, this Report does not constitute investment advice, is not intended to be relied upon as investment advice, is not an endorsement of this project or team, and it is not a guarantee as to the absolute security of the project. CD owes no duty to any third party by virtue of publishing these Reports.
A.2.1 Purpose of Reports
The Reports and the analysis described therein are created solely for Clients and published with their consent. The scope of our review is limited to a review of code and only the code we note as being within the scope of our review within this report. Any Solidity code itself presents unique and unquantifiable risks as the Solidity language itself remains under development and is subject to unknown risks and flaws. The review does not extend to the compiler layer, or any other areas beyond specified code that could present security risks. Cryptographic tokens are emergent technologies and carry with them high levels of technical risk and uncertainty. In some instances, we may perform penetration testing or infrastructure assessments depending on the scope of the particular engagement.
CD makes the Reports available to parties other than the Clients (i.e., “third parties”) on its website. CD hopes that by making these analyses publicly available, it can help the blockchain ecosystem develop technical best practices in this rapidly evolving area of innovation.
A.2.2 Links to Other Web Sites from This Web Site
You may, through hypertext or other computer links, gain access to web sites operated by persons other than Consensys and CD. Such hyperlinks are provided for your reference and convenience only, and are the exclusive responsibility of such web sites’ owners. You agree that Consensys and CD are not responsible for the content or operation of such Web sites, and that Consensys and CD shall have no liability to you or any other person or entity for the use of third party Web sites. Except as described below, a hyperlink from this web Site to another web site does not imply or mean that Consensys and CD endorses the content on that Web site or the operator or operations of that site. You are solely responsible for determining the extent to which you may use any content at any other web sites to which you link from the Reports. Consensys and CD assumes no responsibility for the use of third-party software on the Web Site and shall have no liability whatsoever to any person or entity for the accuracy or completeness of any outcome generated by such software.
A.2.3 Timeliness of Content
The content contained in the Reports is current as of the date appearing on the Report and is subject to change without notice unless indicated otherwise, by Consensys and CD.