@metamask-previews/phishing-controller 13.1.0-preview-5a701133 → 14.0.0-preview-c20b7569
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -1
- package/dist/CacheManager.cjs +177 -0
- package/dist/CacheManager.cjs.map +1 -0
- package/dist/CacheManager.d.cts +104 -0
- package/dist/CacheManager.d.cts.map +1 -0
- package/dist/CacheManager.d.mts +104 -0
- package/dist/CacheManager.d.mts.map +1 -0
- package/dist/CacheManager.mjs +173 -0
- package/dist/CacheManager.mjs.map +1 -0
- package/dist/PhishingController.cjs +186 -8
- package/dist/PhishingController.cjs.map +1 -1
- package/dist/PhishingController.d.cts +41 -6
- package/dist/PhishingController.d.cts.map +1 -1
- package/dist/PhishingController.d.mts +41 -6
- package/dist/PhishingController.d.mts.map +1 -1
- package/dist/PhishingController.mjs +186 -8
- package/dist/PhishingController.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/tests/utils.cjs +79 -1
- package/dist/tests/utils.cjs.map +1 -1
- package/dist/tests/utils.d.cts +59 -0
- package/dist/tests/utils.d.cts.map +1 -1
- package/dist/tests/utils.d.mts +59 -0
- package/dist/tests/utils.d.mts.map +1 -1
- package/dist/tests/utils.mjs +75 -0
- package/dist/tests/utils.mjs.map +1 -1
- package/dist/types.cjs +35 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +68 -0
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +68 -0
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +34 -0
- package/dist/types.mjs.map +1 -1
- package/dist/utils.cjs +54 -1
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +55 -0
- package/dist/utils.d.cts.map +1 -1
- package/dist/utils.d.mts +55 -0
- package/dist/utils.d.mts.map +1 -1
- package/dist/utils.mjs +50 -0
- package/dist/utils.mjs.map +1 -1
- package/package.json +5 -1
- package/dist/UrlScanCache.cjs +0 -127
- package/dist/UrlScanCache.cjs.map +0 -1
- package/dist/UrlScanCache.d.cts +0 -67
- package/dist/UrlScanCache.d.cts.map +0 -1
- package/dist/UrlScanCache.d.mts +0 -67
- package/dist/UrlScanCache.d.mts.map +0 -1
- package/dist/UrlScanCache.mjs +0 -123
- package/dist/UrlScanCache.mjs.map +0 -1
@@ -1,7 +1,8 @@
|
|
1
1
|
import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedMessenger } from "@metamask/base-controller";
|
2
2
|
import { BaseController } from "@metamask/base-controller";
|
3
|
-
import
|
4
|
-
import { type
|
3
|
+
import type { TransactionControllerStateChangeEvent } from "@metamask/transaction-controller";
|
4
|
+
import { type CacheEntry } from "./CacheManager.cjs";
|
5
|
+
import { type PhishingDetectorResult, type PhishingDetectionScanResult, type TokenScanCacheData, type BulkTokenScanResponse, type BulkTokenScanRequest } from "./types.cjs";
|
5
6
|
export declare const PHISHING_CONFIG_BASE_URL = "https://phishing-detection.api.cx.metamask.io";
|
6
7
|
export declare const METAMASK_STALELIST_FILE = "/v1/stalelist";
|
7
8
|
export declare const METAMASK_HOTLIST_DIFF_FILE = "/v1/diffsSince";
|
@@ -10,6 +11,12 @@ export declare const C2_DOMAIN_BLOCKLIST_ENDPOINT = "/v1/request-blocklist";
|
|
10
11
|
export declare const PHISHING_DETECTION_BASE_URL = "https://dapp-scanning.api.cx.metamask.io";
|
11
12
|
export declare const PHISHING_DETECTION_SCAN_ENDPOINT = "v2/scan";
|
12
13
|
export declare const PHISHING_DETECTION_BULK_SCAN_ENDPOINT = "bulk-scan";
|
14
|
+
export declare const SECURITY_ALERTS_BASE_URL = "https://security-alerts.api.cx.metamask.io";
|
15
|
+
export declare const TOKEN_BULK_SCANNING_ENDPOINT = "/token/scan-bulk";
|
16
|
+
export declare const DEFAULT_URL_SCAN_CACHE_TTL: number;
|
17
|
+
export declare const DEFAULT_URL_SCAN_CACHE_MAX_SIZE = 250;
|
18
|
+
export declare const DEFAULT_TOKEN_SCAN_CACHE_TTL: number;
|
19
|
+
export declare const DEFAULT_TOKEN_SCAN_CACHE_MAX_SIZE = 1000;
|
13
20
|
export declare const C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL: number;
|
14
21
|
export declare const HOTLIST_REFRESH_INTERVAL: number;
|
15
22
|
export declare const STALELIST_REFRESH_INTERVAL: number;
|
@@ -153,7 +160,8 @@ export type PhishingControllerState = {
|
|
153
160
|
hotlistLastFetched: number;
|
154
161
|
stalelistLastFetched: number;
|
155
162
|
c2DomainBlocklistLastFetched: number;
|
156
|
-
urlScanCache: Record<string,
|
163
|
+
urlScanCache: Record<string, CacheEntry<PhishingDetectionScanResult>>;
|
164
|
+
tokenScanCache: Record<string, CacheEntry<TokenScanCacheData>>;
|
157
165
|
};
|
158
166
|
/**
|
159
167
|
* PhishingControllerOptions
|
@@ -164,6 +172,8 @@ export type PhishingControllerState = {
|
|
164
172
|
* c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.
|
165
173
|
* urlScanCacheTTL - Time to live in seconds for cached scan results.
|
166
174
|
* urlScanCacheMaxSize - Maximum number of entries in the scan cache.
|
175
|
+
* tokenScanCacheTTL - Time to live in seconds for cached token scan results.
|
176
|
+
* tokenScanCacheMaxSize - Maximum number of entries in the token scan cache.
|
167
177
|
*/
|
168
178
|
export type PhishingControllerOptions = {
|
169
179
|
stalelistRefreshInterval?: number;
|
@@ -171,6 +181,8 @@ export type PhishingControllerOptions = {
|
|
171
181
|
c2DomainBlocklistRefreshInterval?: number;
|
172
182
|
urlScanCacheTTL?: number;
|
173
183
|
urlScanCacheMaxSize?: number;
|
184
|
+
tokenScanCacheTTL?: number;
|
185
|
+
tokenScanCacheMaxSize?: number;
|
174
186
|
messenger: PhishingControllerMessenger;
|
175
187
|
state?: Partial<PhishingControllerState>;
|
176
188
|
};
|
@@ -186,11 +198,23 @@ export type PhishingControllerBulkScanUrlsAction = {
|
|
186
198
|
type: `${typeof controllerName}:bulkScanUrls`;
|
187
199
|
handler: PhishingController['bulkScanUrls'];
|
188
200
|
};
|
201
|
+
export type PhishingControllerBulkScanTokensAction = {
|
202
|
+
type: `${typeof controllerName}:bulkScanTokens`;
|
203
|
+
handler: PhishingController['bulkScanTokens'];
|
204
|
+
};
|
189
205
|
export type PhishingControllerGetStateAction = ControllerGetStateAction<typeof controllerName, PhishingControllerState>;
|
190
|
-
export type PhishingControllerActions = PhishingControllerGetStateAction | MaybeUpdateState | TestOrigin | PhishingControllerBulkScanUrlsAction;
|
206
|
+
export type PhishingControllerActions = PhishingControllerGetStateAction | MaybeUpdateState | TestOrigin | PhishingControllerBulkScanUrlsAction | PhishingControllerBulkScanTokensAction;
|
191
207
|
export type PhishingControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, PhishingControllerState>;
|
192
208
|
export type PhishingControllerEvents = PhishingControllerStateChangeEvent;
|
193
|
-
|
209
|
+
/**
|
210
|
+
* The external actions available to the PhishingController.
|
211
|
+
*/
|
212
|
+
type AllowedActions = never;
|
213
|
+
/**
|
214
|
+
* The external events available to the PhishingController.
|
215
|
+
*/
|
216
|
+
export type AllowedEvents = TransactionControllerStateChangeEvent;
|
217
|
+
export type PhishingControllerMessenger = RestrictedMessenger<typeof controllerName, PhishingControllerActions | AllowedActions, PhishingControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
|
194
218
|
/**
|
195
219
|
* BulkPhishingDetectionScanResponse
|
196
220
|
*
|
@@ -217,10 +241,12 @@ export declare class PhishingController extends BaseController<typeof controller
|
|
217
241
|
* @param config.c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.
|
218
242
|
* @param config.urlScanCacheTTL - Time to live in seconds for cached scan results.
|
219
243
|
* @param config.urlScanCacheMaxSize - Maximum number of entries in the scan cache.
|
244
|
+
* @param config.tokenScanCacheTTL - Time to live in seconds for cached token scan results.
|
245
|
+
* @param config.tokenScanCacheMaxSize - Maximum number of entries in the token scan cache.
|
220
246
|
* @param config.messenger - The controller restricted messenger.
|
221
247
|
* @param config.state - Initial state to set on this controller.
|
222
248
|
*/
|
223
|
-
constructor({ stalelistRefreshInterval, hotlistRefreshInterval, c2DomainBlocklistRefreshInterval, urlScanCacheTTL, urlScanCacheMaxSize, messenger, state, }: PhishingControllerOptions);
|
249
|
+
constructor({ stalelistRefreshInterval, hotlistRefreshInterval, c2DomainBlocklistRefreshInterval, urlScanCacheTTL, urlScanCacheMaxSize, tokenScanCacheTTL, tokenScanCacheMaxSize, messenger, state, }: PhishingControllerOptions);
|
224
250
|
/**
|
225
251
|
* Updates this.detector with an instance of PhishingDetector using the current state.
|
226
252
|
*/
|
@@ -357,6 +383,15 @@ export declare class PhishingController extends BaseController<typeof controller
|
|
357
383
|
* @returns A mapping of URLs to their phishing detection scan results and errors.
|
358
384
|
*/
|
359
385
|
bulkScanUrls: (urls: string[]) => Promise<BulkPhishingDetectionScanResponse>;
|
386
|
+
/**
|
387
|
+
* Scan multiple tokens for malicious activity in bulk.
|
388
|
+
*
|
389
|
+
* @param request - The bulk scan request containing chainId and tokens.
|
390
|
+
* @param request.chainId - The chain ID in hex format (e.g., '0x1' for Ethereum).
|
391
|
+
* @param request.tokens - Array of token addresses to scan.
|
392
|
+
* @returns A mapping of lowercase token addresses to their scan results. Tokens that fail to scan are omitted.
|
393
|
+
*/
|
394
|
+
bulkScanTokens: (request: BulkTokenScanRequest) => Promise<BulkTokenScanResponse>;
|
360
395
|
}
|
361
396
|
export default PhishingController;
|
362
397
|
export type { PhishingDetectorResult };
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"PhishingController.d.cts","sourceRoot":"","sources":["../src/PhishingController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EAEpB,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;
|
1
|
+
{"version":3,"file":"PhishingController.d.cts","sourceRoot":"","sources":["../src/PhishingController.ts"],"names":[],"mappings":"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"}
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedMessenger } from "@metamask/base-controller";
|
2
2
|
import { BaseController } from "@metamask/base-controller";
|
3
|
-
import
|
4
|
-
import { type
|
3
|
+
import type { TransactionControllerStateChangeEvent } from "@metamask/transaction-controller";
|
4
|
+
import { type CacheEntry } from "./CacheManager.mjs";
|
5
|
+
import { type PhishingDetectorResult, type PhishingDetectionScanResult, type TokenScanCacheData, type BulkTokenScanResponse, type BulkTokenScanRequest } from "./types.mjs";
|
5
6
|
export declare const PHISHING_CONFIG_BASE_URL = "https://phishing-detection.api.cx.metamask.io";
|
6
7
|
export declare const METAMASK_STALELIST_FILE = "/v1/stalelist";
|
7
8
|
export declare const METAMASK_HOTLIST_DIFF_FILE = "/v1/diffsSince";
|
@@ -10,6 +11,12 @@ export declare const C2_DOMAIN_BLOCKLIST_ENDPOINT = "/v1/request-blocklist";
|
|
10
11
|
export declare const PHISHING_DETECTION_BASE_URL = "https://dapp-scanning.api.cx.metamask.io";
|
11
12
|
export declare const PHISHING_DETECTION_SCAN_ENDPOINT = "v2/scan";
|
12
13
|
export declare const PHISHING_DETECTION_BULK_SCAN_ENDPOINT = "bulk-scan";
|
14
|
+
export declare const SECURITY_ALERTS_BASE_URL = "https://security-alerts.api.cx.metamask.io";
|
15
|
+
export declare const TOKEN_BULK_SCANNING_ENDPOINT = "/token/scan-bulk";
|
16
|
+
export declare const DEFAULT_URL_SCAN_CACHE_TTL: number;
|
17
|
+
export declare const DEFAULT_URL_SCAN_CACHE_MAX_SIZE = 250;
|
18
|
+
export declare const DEFAULT_TOKEN_SCAN_CACHE_TTL: number;
|
19
|
+
export declare const DEFAULT_TOKEN_SCAN_CACHE_MAX_SIZE = 1000;
|
13
20
|
export declare const C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL: number;
|
14
21
|
export declare const HOTLIST_REFRESH_INTERVAL: number;
|
15
22
|
export declare const STALELIST_REFRESH_INTERVAL: number;
|
@@ -153,7 +160,8 @@ export type PhishingControllerState = {
|
|
153
160
|
hotlistLastFetched: number;
|
154
161
|
stalelistLastFetched: number;
|
155
162
|
c2DomainBlocklistLastFetched: number;
|
156
|
-
urlScanCache: Record<string,
|
163
|
+
urlScanCache: Record<string, CacheEntry<PhishingDetectionScanResult>>;
|
164
|
+
tokenScanCache: Record<string, CacheEntry<TokenScanCacheData>>;
|
157
165
|
};
|
158
166
|
/**
|
159
167
|
* PhishingControllerOptions
|
@@ -164,6 +172,8 @@ export type PhishingControllerState = {
|
|
164
172
|
* c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.
|
165
173
|
* urlScanCacheTTL - Time to live in seconds for cached scan results.
|
166
174
|
* urlScanCacheMaxSize - Maximum number of entries in the scan cache.
|
175
|
+
* tokenScanCacheTTL - Time to live in seconds for cached token scan results.
|
176
|
+
* tokenScanCacheMaxSize - Maximum number of entries in the token scan cache.
|
167
177
|
*/
|
168
178
|
export type PhishingControllerOptions = {
|
169
179
|
stalelistRefreshInterval?: number;
|
@@ -171,6 +181,8 @@ export type PhishingControllerOptions = {
|
|
171
181
|
c2DomainBlocklistRefreshInterval?: number;
|
172
182
|
urlScanCacheTTL?: number;
|
173
183
|
urlScanCacheMaxSize?: number;
|
184
|
+
tokenScanCacheTTL?: number;
|
185
|
+
tokenScanCacheMaxSize?: number;
|
174
186
|
messenger: PhishingControllerMessenger;
|
175
187
|
state?: Partial<PhishingControllerState>;
|
176
188
|
};
|
@@ -186,11 +198,23 @@ export type PhishingControllerBulkScanUrlsAction = {
|
|
186
198
|
type: `${typeof controllerName}:bulkScanUrls`;
|
187
199
|
handler: PhishingController['bulkScanUrls'];
|
188
200
|
};
|
201
|
+
export type PhishingControllerBulkScanTokensAction = {
|
202
|
+
type: `${typeof controllerName}:bulkScanTokens`;
|
203
|
+
handler: PhishingController['bulkScanTokens'];
|
204
|
+
};
|
189
205
|
export type PhishingControllerGetStateAction = ControllerGetStateAction<typeof controllerName, PhishingControllerState>;
|
190
|
-
export type PhishingControllerActions = PhishingControllerGetStateAction | MaybeUpdateState | TestOrigin | PhishingControllerBulkScanUrlsAction;
|
206
|
+
export type PhishingControllerActions = PhishingControllerGetStateAction | MaybeUpdateState | TestOrigin | PhishingControllerBulkScanUrlsAction | PhishingControllerBulkScanTokensAction;
|
191
207
|
export type PhishingControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, PhishingControllerState>;
|
192
208
|
export type PhishingControllerEvents = PhishingControllerStateChangeEvent;
|
193
|
-
|
209
|
+
/**
|
210
|
+
* The external actions available to the PhishingController.
|
211
|
+
*/
|
212
|
+
type AllowedActions = never;
|
213
|
+
/**
|
214
|
+
* The external events available to the PhishingController.
|
215
|
+
*/
|
216
|
+
export type AllowedEvents = TransactionControllerStateChangeEvent;
|
217
|
+
export type PhishingControllerMessenger = RestrictedMessenger<typeof controllerName, PhishingControllerActions | AllowedActions, PhishingControllerEvents | AllowedEvents, AllowedActions['type'], AllowedEvents['type']>;
|
194
218
|
/**
|
195
219
|
* BulkPhishingDetectionScanResponse
|
196
220
|
*
|
@@ -217,10 +241,12 @@ export declare class PhishingController extends BaseController<typeof controller
|
|
217
241
|
* @param config.c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.
|
218
242
|
* @param config.urlScanCacheTTL - Time to live in seconds for cached scan results.
|
219
243
|
* @param config.urlScanCacheMaxSize - Maximum number of entries in the scan cache.
|
244
|
+
* @param config.tokenScanCacheTTL - Time to live in seconds for cached token scan results.
|
245
|
+
* @param config.tokenScanCacheMaxSize - Maximum number of entries in the token scan cache.
|
220
246
|
* @param config.messenger - The controller restricted messenger.
|
221
247
|
* @param config.state - Initial state to set on this controller.
|
222
248
|
*/
|
223
|
-
constructor({ stalelistRefreshInterval, hotlistRefreshInterval, c2DomainBlocklistRefreshInterval, urlScanCacheTTL, urlScanCacheMaxSize, messenger, state, }: PhishingControllerOptions);
|
249
|
+
constructor({ stalelistRefreshInterval, hotlistRefreshInterval, c2DomainBlocklistRefreshInterval, urlScanCacheTTL, urlScanCacheMaxSize, tokenScanCacheTTL, tokenScanCacheMaxSize, messenger, state, }: PhishingControllerOptions);
|
224
250
|
/**
|
225
251
|
* Updates this.detector with an instance of PhishingDetector using the current state.
|
226
252
|
*/
|
@@ -357,6 +383,15 @@ export declare class PhishingController extends BaseController<typeof controller
|
|
357
383
|
* @returns A mapping of URLs to their phishing detection scan results and errors.
|
358
384
|
*/
|
359
385
|
bulkScanUrls: (urls: string[]) => Promise<BulkPhishingDetectionScanResponse>;
|
386
|
+
/**
|
387
|
+
* Scan multiple tokens for malicious activity in bulk.
|
388
|
+
*
|
389
|
+
* @param request - The bulk scan request containing chainId and tokens.
|
390
|
+
* @param request.chainId - The chain ID in hex format (e.g., '0x1' for Ethereum).
|
391
|
+
* @param request.tokens - Array of token addresses to scan.
|
392
|
+
* @returns A mapping of lowercase token addresses to their scan results. Tokens that fail to scan are omitted.
|
393
|
+
*/
|
394
|
+
bulkScanTokens: (request: BulkTokenScanRequest) => Promise<BulkTokenScanResponse>;
|
360
395
|
}
|
361
396
|
export default PhishingController;
|
362
397
|
export type { PhishingDetectorResult };
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"PhishingController.d.mts","sourceRoot":"","sources":["../src/PhishingController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,mBAAmB,EAEpB,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;
|
1
|
+
{"version":3,"file":"PhishingController.d.mts","sourceRoot":"","sources":["../src/PhishingController.ts"],"names":[],"mappings":"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"}
|
@@ -9,15 +9,15 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
11
11
|
};
|
12
|
-
var _PhishingController_instances, _PhishingController_detector, _PhishingController_stalelistRefreshInterval, _PhishingController_hotlistRefreshInterval, _PhishingController_c2DomainBlocklistRefreshInterval, _PhishingController_urlScanCache, _PhishingController_inProgressHotlistUpdate, _PhishingController_inProgressStalelistUpdate, _PhishingController_isProgressC2DomainBlocklistUpdate, _PhishingController_registerMessageHandlers, _PhishingController_processBatch, _PhishingController_updateStalelist, _PhishingController_updateHotlist, _PhishingController_updateC2DomainBlocklist, _PhishingController_queryConfig;
|
12
|
+
var _PhishingController_instances, _PhishingController_detector, _PhishingController_stalelistRefreshInterval, _PhishingController_hotlistRefreshInterval, _PhishingController_c2DomainBlocklistRefreshInterval, _PhishingController_urlScanCache, _PhishingController_tokenScanCache, _PhishingController_inProgressHotlistUpdate, _PhishingController_inProgressStalelistUpdate, _PhishingController_isProgressC2DomainBlocklistUpdate, _PhishingController_transactionControllerStateChangeHandler, _PhishingController_subscribeToTransactionControllerStateChange, _PhishingController_registerMessageHandlers, _PhishingController_isTransactionPatch, _PhishingController_onTransactionControllerStateChange, _PhishingController_getTokensFromTransaction, _PhishingController_scanTokensByChain, _PhishingController_fetchTokenScanBulkResults, _PhishingController_processBatch, _PhishingController_updateStalelist, _PhishingController_updateHotlist, _PhishingController_updateC2DomainBlocklist, _PhishingController_queryConfig;
|
13
13
|
import { BaseController } from "@metamask/base-controller";
|
14
14
|
import { safelyExecute, safelyExecuteWithTimeout } from "@metamask/controller-utils";
|
15
15
|
import $punycodepunycodejs from "punycode/punycode.js";
|
16
16
|
const { toASCII } = $punycodepunycodejs;
|
17
|
+
import { CacheManager } from "./CacheManager.mjs";
|
17
18
|
import { PhishingDetector } from "./PhishingDetector.mjs";
|
18
19
|
import { PhishingDetectorResultType, RecommendedAction } from "./types.mjs";
|
19
|
-
import {
|
20
|
-
import { applyDiffs, fetchTimeNow, getHostnameFromUrl, roundToNearestMinute, getHostnameFromWebUrl } from "./utils.mjs";
|
20
|
+
import { applyDiffs, fetchTimeNow, getHostnameFromUrl, roundToNearestMinute, getHostnameFromWebUrl, buildCacheKey, splitCacheHits, resolveChainName } from "./utils.mjs";
|
21
21
|
export const PHISHING_CONFIG_BASE_URL = 'https://phishing-detection.api.cx.metamask.io';
|
22
22
|
export const METAMASK_STALELIST_FILE = '/v1/stalelist';
|
23
23
|
export const METAMASK_HOTLIST_DIFF_FILE = '/v1/diffsSince';
|
@@ -26,6 +26,13 @@ export const C2_DOMAIN_BLOCKLIST_ENDPOINT = '/v1/request-blocklist';
|
|
26
26
|
export const PHISHING_DETECTION_BASE_URL = 'https://dapp-scanning.api.cx.metamask.io';
|
27
27
|
export const PHISHING_DETECTION_SCAN_ENDPOINT = 'v2/scan';
|
28
28
|
export const PHISHING_DETECTION_BULK_SCAN_ENDPOINT = 'bulk-scan';
|
29
|
+
export const SECURITY_ALERTS_BASE_URL = 'https://security-alerts.api.cx.metamask.io';
|
30
|
+
export const TOKEN_BULK_SCANNING_ENDPOINT = '/token/scan-bulk';
|
31
|
+
// Cache configuration defaults
|
32
|
+
export const DEFAULT_URL_SCAN_CACHE_TTL = 15 * 60; // 15 minutes in seconds
|
33
|
+
export const DEFAULT_URL_SCAN_CACHE_MAX_SIZE = 250;
|
34
|
+
export const DEFAULT_TOKEN_SCAN_CACHE_TTL = 15 * 60; // 15 minutes in seconds
|
35
|
+
export const DEFAULT_TOKEN_SCAN_CACHE_MAX_SIZE = 1000;
|
29
36
|
export const C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL = 5 * 60; // 5 mins in seconds
|
30
37
|
export const HOTLIST_REFRESH_INTERVAL = 5 * 60; // 5 mins in seconds
|
31
38
|
export const STALELIST_REFRESH_INTERVAL = 30 * 24 * 60 * 60; // 30 days in seconds
|
@@ -99,6 +106,12 @@ const metadata = {
|
|
99
106
|
anonymous: false,
|
100
107
|
usedInUi: true,
|
101
108
|
},
|
109
|
+
tokenScanCache: {
|
110
|
+
includeInStateLogs: false,
|
111
|
+
persist: true,
|
112
|
+
anonymous: false,
|
113
|
+
usedInUi: true,
|
114
|
+
},
|
102
115
|
};
|
103
116
|
/**
|
104
117
|
* Get a default empty state for the controller.
|
@@ -112,6 +125,7 @@ const getDefaultState = () => {
|
|
112
125
|
stalelistLastFetched: 0,
|
113
126
|
c2DomainBlocklistLastFetched: 0,
|
114
127
|
urlScanCache: {},
|
128
|
+
tokenScanCache: {},
|
115
129
|
};
|
116
130
|
};
|
117
131
|
/**
|
@@ -127,10 +141,12 @@ export class PhishingController extends BaseController {
|
|
127
141
|
* @param config.c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.
|
128
142
|
* @param config.urlScanCacheTTL - Time to live in seconds for cached scan results.
|
129
143
|
* @param config.urlScanCacheMaxSize - Maximum number of entries in the scan cache.
|
144
|
+
* @param config.tokenScanCacheTTL - Time to live in seconds for cached token scan results.
|
145
|
+
* @param config.tokenScanCacheMaxSize - Maximum number of entries in the token scan cache.
|
130
146
|
* @param config.messenger - The controller restricted messenger.
|
131
147
|
* @param config.state - Initial state to set on this controller.
|
132
148
|
*/
|
133
|
-
constructor({ stalelistRefreshInterval = STALELIST_REFRESH_INTERVAL, hotlistRefreshInterval = HOTLIST_REFRESH_INTERVAL, c2DomainBlocklistRefreshInterval = C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL, urlScanCacheTTL = DEFAULT_URL_SCAN_CACHE_TTL, urlScanCacheMaxSize = DEFAULT_URL_SCAN_CACHE_MAX_SIZE, messenger, state = {}, }) {
|
149
|
+
constructor({ stalelistRefreshInterval = STALELIST_REFRESH_INTERVAL, hotlistRefreshInterval = HOTLIST_REFRESH_INTERVAL, c2DomainBlocklistRefreshInterval = C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL, urlScanCacheTTL = DEFAULT_URL_SCAN_CACHE_TTL, urlScanCacheMaxSize = DEFAULT_URL_SCAN_CACHE_MAX_SIZE, tokenScanCacheTTL = DEFAULT_TOKEN_SCAN_CACHE_TTL, tokenScanCacheMaxSize = DEFAULT_TOKEN_SCAN_CACHE_MAX_SIZE, messenger, state = {}, }) {
|
134
150
|
super({
|
135
151
|
name: controllerName,
|
136
152
|
metadata,
|
@@ -148,9 +164,11 @@ export class PhishingController extends BaseController {
|
|
148
164
|
_PhishingController_hotlistRefreshInterval.set(this, void 0);
|
149
165
|
_PhishingController_c2DomainBlocklistRefreshInterval.set(this, void 0);
|
150
166
|
_PhishingController_urlScanCache.set(this, void 0);
|
167
|
+
_PhishingController_tokenScanCache.set(this, void 0);
|
151
168
|
_PhishingController_inProgressHotlistUpdate.set(this, void 0);
|
152
169
|
_PhishingController_inProgressStalelistUpdate.set(this, void 0);
|
153
170
|
_PhishingController_isProgressC2DomainBlocklistUpdate.set(this, void 0);
|
171
|
+
_PhishingController_transactionControllerStateChangeHandler.set(this, void 0);
|
154
172
|
/**
|
155
173
|
* Scan a URL for phishing. It will only scan the hostname of the URL. It also only supports
|
156
174
|
* web URLs.
|
@@ -205,7 +223,7 @@ export class PhishingController extends BaseController {
|
|
205
223
|
hostname,
|
206
224
|
recommendedAction: apiResponse.recommendedAction,
|
207
225
|
};
|
208
|
-
__classPrivateFieldGet(this, _PhishingController_urlScanCache, "f").
|
226
|
+
__classPrivateFieldGet(this, _PhishingController_urlScanCache, "f").set(hostname, result);
|
209
227
|
return result;
|
210
228
|
};
|
211
229
|
/**
|
@@ -282,7 +300,7 @@ export class PhishingController extends BaseController {
|
|
282
300
|
Object.entries(batchResponse.results).forEach(([url, result]) => {
|
283
301
|
const hostname = urlsToHostnames[url];
|
284
302
|
if (hostname) {
|
285
|
-
__classPrivateFieldGet(this, _PhishingController_urlScanCache, "f").
|
303
|
+
__classPrivateFieldGet(this, _PhishingController_urlScanCache, "f").set(hostname, result);
|
286
304
|
}
|
287
305
|
combinedResponse.results[url] = result;
|
288
306
|
});
|
@@ -297,6 +315,102 @@ export class PhishingController extends BaseController {
|
|
297
315
|
}
|
298
316
|
return combinedResponse;
|
299
317
|
};
|
318
|
+
/**
|
319
|
+
* Fetch bulk token scan results from the security alerts API.
|
320
|
+
*
|
321
|
+
* @param chain - The chain name.
|
322
|
+
* @param tokens - Array of token addresses to scan.
|
323
|
+
* @returns The API response or null if there was an error.
|
324
|
+
*/
|
325
|
+
_PhishingController_fetchTokenScanBulkResults.set(this, async (chain, tokens) => {
|
326
|
+
const timeout = 8000; // 8 seconds
|
327
|
+
const apiResponse = await safelyExecuteWithTimeout(async () => {
|
328
|
+
const response = await fetch(`${SECURITY_ALERTS_BASE_URL}${TOKEN_BULK_SCANNING_ENDPOINT}`, {
|
329
|
+
method: 'POST',
|
330
|
+
headers: {
|
331
|
+
Accept: 'application/json',
|
332
|
+
'Content-Type': 'application/json',
|
333
|
+
},
|
334
|
+
body: JSON.stringify({
|
335
|
+
chain,
|
336
|
+
tokens,
|
337
|
+
}),
|
338
|
+
});
|
339
|
+
if (!response.ok) {
|
340
|
+
return {
|
341
|
+
error: `${response.status} ${response.statusText}`,
|
342
|
+
status: response.status,
|
343
|
+
statusText: response.statusText,
|
344
|
+
};
|
345
|
+
}
|
346
|
+
const data = await response.json();
|
347
|
+
return data;
|
348
|
+
}, true, timeout);
|
349
|
+
if (!apiResponse) {
|
350
|
+
console.error(`Error scanning tokens: timeout of ${timeout}ms exceeded`);
|
351
|
+
return null;
|
352
|
+
}
|
353
|
+
if ('error' in apiResponse &&
|
354
|
+
'status' in apiResponse &&
|
355
|
+
'statusText' in apiResponse) {
|
356
|
+
console.warn(`Token bulk screening API error: ${apiResponse.status} ${apiResponse.statusText}`);
|
357
|
+
return null;
|
358
|
+
}
|
359
|
+
return apiResponse;
|
360
|
+
});
|
361
|
+
/**
|
362
|
+
* Scan multiple tokens for malicious activity in bulk.
|
363
|
+
*
|
364
|
+
* @param request - The bulk scan request containing chainId and tokens.
|
365
|
+
* @param request.chainId - The chain ID in hex format (e.g., '0x1' for Ethereum).
|
366
|
+
* @param request.tokens - Array of token addresses to scan.
|
367
|
+
* @returns A mapping of lowercase token addresses to their scan results. Tokens that fail to scan are omitted.
|
368
|
+
*/
|
369
|
+
this.bulkScanTokens = async (request) => {
|
370
|
+
const { chainId, tokens } = request;
|
371
|
+
if (!tokens || tokens.length === 0) {
|
372
|
+
return {};
|
373
|
+
}
|
374
|
+
const MAX_TOKENS_PER_REQUEST = 100;
|
375
|
+
if (tokens.length > MAX_TOKENS_PER_REQUEST) {
|
376
|
+
console.warn(`Maximum of ${MAX_TOKENS_PER_REQUEST} tokens allowed per request`);
|
377
|
+
return {};
|
378
|
+
}
|
379
|
+
const normalizedChainId = chainId.toLowerCase();
|
380
|
+
const chain = resolveChainName(normalizedChainId);
|
381
|
+
if (!chain) {
|
382
|
+
console.warn(`Unknown chain ID: ${chainId}`);
|
383
|
+
return {};
|
384
|
+
}
|
385
|
+
// Split tokens into cached results and tokens that need to be fetched
|
386
|
+
const { cachedResults, tokensToFetch } = splitCacheHits(__classPrivateFieldGet(this, _PhishingController_tokenScanCache, "f"), normalizedChainId, tokens);
|
387
|
+
const results = { ...cachedResults };
|
388
|
+
// If there are tokens to fetch, call the bulk token scan API
|
389
|
+
if (tokensToFetch.length > 0) {
|
390
|
+
const apiResponse = await __classPrivateFieldGet(this, _PhishingController_fetchTokenScanBulkResults, "f").call(this, chain, tokensToFetch);
|
391
|
+
if (apiResponse?.results) {
|
392
|
+
// Process API results and update cache
|
393
|
+
for (const tokenAddress of tokensToFetch) {
|
394
|
+
const normalizedAddress = tokenAddress.toLowerCase();
|
395
|
+
const tokenResult = apiResponse.results[normalizedAddress];
|
396
|
+
if (tokenResult?.result_type) {
|
397
|
+
const result = {
|
398
|
+
result_type: tokenResult.result_type,
|
399
|
+
chain: tokenResult.chain || normalizedChainId,
|
400
|
+
address: tokenResult.address || normalizedAddress,
|
401
|
+
};
|
402
|
+
// Update cache
|
403
|
+
const cacheKey = buildCacheKey(normalizedChainId, normalizedAddress);
|
404
|
+
__classPrivateFieldGet(this, _PhishingController_tokenScanCache, "f").set(cacheKey, {
|
405
|
+
result_type: tokenResult.result_type,
|
406
|
+
});
|
407
|
+
results[normalizedAddress] = result;
|
408
|
+
}
|
409
|
+
}
|
410
|
+
}
|
411
|
+
}
|
412
|
+
return results;
|
413
|
+
};
|
300
414
|
/**
|
301
415
|
* Process a batch of URLs (up to 50) for phishing detection.
|
302
416
|
*
|
@@ -348,7 +462,8 @@ export class PhishingController extends BaseController {
|
|
348
462
|
__classPrivateFieldSet(this, _PhishingController_stalelistRefreshInterval, stalelistRefreshInterval, "f");
|
349
463
|
__classPrivateFieldSet(this, _PhishingController_hotlistRefreshInterval, hotlistRefreshInterval, "f");
|
350
464
|
__classPrivateFieldSet(this, _PhishingController_c2DomainBlocklistRefreshInterval, c2DomainBlocklistRefreshInterval, "f");
|
351
|
-
__classPrivateFieldSet(this,
|
465
|
+
__classPrivateFieldSet(this, _PhishingController_transactionControllerStateChangeHandler, __classPrivateFieldGet(this, _PhishingController_instances, "m", _PhishingController_onTransactionControllerStateChange).bind(this), "f");
|
466
|
+
__classPrivateFieldSet(this, _PhishingController_urlScanCache, new CacheManager({
|
352
467
|
cacheTTL: urlScanCacheTTL,
|
353
468
|
maxCacheSize: urlScanCacheMaxSize,
|
354
469
|
initialCache: this.state.urlScanCache,
|
@@ -358,8 +473,19 @@ export class PhishingController extends BaseController {
|
|
358
473
|
});
|
359
474
|
},
|
360
475
|
}), "f");
|
476
|
+
__classPrivateFieldSet(this, _PhishingController_tokenScanCache, new CacheManager({
|
477
|
+
cacheTTL: tokenScanCacheTTL,
|
478
|
+
maxCacheSize: tokenScanCacheMaxSize,
|
479
|
+
initialCache: this.state.tokenScanCache,
|
480
|
+
updateState: (cache) => {
|
481
|
+
this.update((draftState) => {
|
482
|
+
draftState.tokenScanCache = cache;
|
483
|
+
});
|
484
|
+
},
|
485
|
+
}), "f");
|
361
486
|
__classPrivateFieldGet(this, _PhishingController_instances, "m", _PhishingController_registerMessageHandlers).call(this);
|
362
487
|
this.updatePhishingDetector();
|
488
|
+
__classPrivateFieldGet(this, _PhishingController_instances, "m", _PhishingController_subscribeToTransactionControllerStateChange).call(this);
|
363
489
|
}
|
364
490
|
/**
|
365
491
|
* Updates this.detector with an instance of PhishingDetector using the current state.
|
@@ -579,10 +705,62 @@ export class PhishingController extends BaseController {
|
|
579
705
|
}
|
580
706
|
}
|
581
707
|
}
|
582
|
-
_PhishingController_detector = new WeakMap(), _PhishingController_stalelistRefreshInterval = new WeakMap(), _PhishingController_hotlistRefreshInterval = new WeakMap(), _PhishingController_c2DomainBlocklistRefreshInterval = new WeakMap(), _PhishingController_urlScanCache = new WeakMap(), _PhishingController_inProgressHotlistUpdate = new WeakMap(), _PhishingController_inProgressStalelistUpdate = new WeakMap(), _PhishingController_isProgressC2DomainBlocklistUpdate = new WeakMap(), _PhishingController_processBatch = new WeakMap(), _PhishingController_instances = new WeakSet(),
|
708
|
+
_PhishingController_detector = new WeakMap(), _PhishingController_stalelistRefreshInterval = new WeakMap(), _PhishingController_hotlistRefreshInterval = new WeakMap(), _PhishingController_c2DomainBlocklistRefreshInterval = new WeakMap(), _PhishingController_urlScanCache = new WeakMap(), _PhishingController_tokenScanCache = new WeakMap(), _PhishingController_inProgressHotlistUpdate = new WeakMap(), _PhishingController_inProgressStalelistUpdate = new WeakMap(), _PhishingController_isProgressC2DomainBlocklistUpdate = new WeakMap(), _PhishingController_transactionControllerStateChangeHandler = new WeakMap(), _PhishingController_fetchTokenScanBulkResults = new WeakMap(), _PhishingController_processBatch = new WeakMap(), _PhishingController_instances = new WeakSet(), _PhishingController_subscribeToTransactionControllerStateChange = function _PhishingController_subscribeToTransactionControllerStateChange() {
|
709
|
+
this.messagingSystem.subscribe('TransactionController:stateChange', __classPrivateFieldGet(this, _PhishingController_transactionControllerStateChangeHandler, "f"));
|
710
|
+
}, _PhishingController_registerMessageHandlers = function _PhishingController_registerMessageHandlers() {
|
583
711
|
this.messagingSystem.registerActionHandler(`${controllerName}:maybeUpdateState`, this.maybeUpdateState.bind(this));
|
584
712
|
this.messagingSystem.registerActionHandler(`${controllerName}:testOrigin`, this.test.bind(this));
|
585
713
|
this.messagingSystem.registerActionHandler(`${controllerName}:bulkScanUrls`, this.bulkScanUrls.bind(this));
|
714
|
+
this.messagingSystem.registerActionHandler(`${controllerName}:bulkScanTokens`, this.bulkScanTokens.bind(this));
|
715
|
+
}, _PhishingController_isTransactionPatch = function _PhishingController_isTransactionPatch(patch) {
|
716
|
+
const { path } = patch;
|
717
|
+
return (path.length === 2 &&
|
718
|
+
path[0] === 'transactions' &&
|
719
|
+
typeof path[1] === 'number');
|
720
|
+
}, _PhishingController_onTransactionControllerStateChange = function _PhishingController_onTransactionControllerStateChange(_state, patches) {
|
721
|
+
try {
|
722
|
+
const tokensByChain = new Map();
|
723
|
+
for (const patch of patches) {
|
724
|
+
if (patch.op === 'remove') {
|
725
|
+
continue;
|
726
|
+
}
|
727
|
+
// Handle transaction-level patches (includes simulation data updates)
|
728
|
+
if (__classPrivateFieldGet(this, _PhishingController_instances, "m", _PhishingController_isTransactionPatch).call(this, patch)) {
|
729
|
+
const transaction = patch.value;
|
730
|
+
__classPrivateFieldGet(this, _PhishingController_instances, "m", _PhishingController_getTokensFromTransaction).call(this, transaction, tokensByChain);
|
731
|
+
}
|
732
|
+
}
|
733
|
+
__classPrivateFieldGet(this, _PhishingController_instances, "m", _PhishingController_scanTokensByChain).call(this, tokensByChain);
|
734
|
+
}
|
735
|
+
catch (error) {
|
736
|
+
console.error('Error processing transaction state change:', error);
|
737
|
+
}
|
738
|
+
}, _PhishingController_getTokensFromTransaction = function _PhishingController_getTokensFromTransaction(transaction, tokensByChain) {
|
739
|
+
// extract token addresses from simulation data
|
740
|
+
const tokenAddresses = transaction.simulationData?.tokenBalanceChanges?.map((tokenChange) => tokenChange.address.toLowerCase());
|
741
|
+
// add token addresses to the map by chainId
|
742
|
+
if (tokenAddresses && tokenAddresses.length > 0 && transaction.chainId) {
|
743
|
+
const chainId = transaction.chainId.toLowerCase();
|
744
|
+
if (!tokensByChain.has(chainId)) {
|
745
|
+
tokensByChain.set(chainId, new Set());
|
746
|
+
}
|
747
|
+
const chainTokens = tokensByChain.get(chainId);
|
748
|
+
if (chainTokens) {
|
749
|
+
for (const address of tokenAddresses) {
|
750
|
+
chainTokens.add(address);
|
751
|
+
}
|
752
|
+
}
|
753
|
+
}
|
754
|
+
}, _PhishingController_scanTokensByChain = function _PhishingController_scanTokensByChain(tokensByChain) {
|
755
|
+
for (const [chainId, tokenSet] of tokensByChain) {
|
756
|
+
if (tokenSet.size > 0) {
|
757
|
+
const tokens = Array.from(tokenSet);
|
758
|
+
this.bulkScanTokens({
|
759
|
+
chainId,
|
760
|
+
tokens,
|
761
|
+
}).catch((error) => console.error(`Error scanning tokens for chain ${chainId}:`, error));
|
762
|
+
}
|
763
|
+
}
|
586
764
|
}, _PhishingController_updateStalelist =
|
587
765
|
/**
|
588
766
|
* Update the stalelist configuration.
|