@metamask-previews/phishing-controller 12.4.1-preview-6df5889d → 12.5.0-preview-72122b6f
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 +19 -1
- package/dist/PhishingController.cjs +187 -6
- package/dist/PhishingController.cjs.map +1 -1
- package/dist/PhishingController.d.cts +50 -5
- package/dist/PhishingController.d.cts.map +1 -1
- package/dist/PhishingController.d.mts +50 -5
- package/dist/PhishingController.d.mts.map +1 -1
- package/dist/PhishingController.mjs +186 -5
- package/dist/PhishingController.mjs.map +1 -1
- package/dist/UrlScanCache.cjs +127 -0
- package/dist/UrlScanCache.cjs.map +1 -0
- package/dist/UrlScanCache.d.cts +67 -0
- package/dist/UrlScanCache.d.cts.map +1 -0
- package/dist/UrlScanCache.d.mts +67 -0
- package/dist/UrlScanCache.d.mts.map +1 -0
- package/dist/UrlScanCache.mjs +123 -0
- package/dist/UrlScanCache.mjs.map +1 -0
- package/package.json +1 -1
@@ -1,6 +1,7 @@
|
|
1
1
|
import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedMessenger } from "@metamask/base-controller";
|
2
2
|
import { BaseController } from "@metamask/base-controller";
|
3
3
|
import { type PhishingDetectorResult, type PhishingDetectionScanResult } from "./types.cjs";
|
4
|
+
import { type UrlScanCacheEntry } from "./UrlScanCache.cjs";
|
4
5
|
export declare const PHISHING_CONFIG_BASE_URL = "https://phishing-detection.api.cx.metamask.io";
|
5
6
|
export declare const METAMASK_STALELIST_FILE = "/v1/stalelist";
|
6
7
|
export declare const METAMASK_HOTLIST_DIFF_FILE = "/v1/diffsSince";
|
@@ -8,6 +9,7 @@ export declare const CLIENT_SIDE_DETECION_BASE_URL = "https://client-side-detect
|
|
8
9
|
export declare const C2_DOMAIN_BLOCKLIST_ENDPOINT = "/v1/request-blocklist";
|
9
10
|
export declare const PHISHING_DETECTION_BASE_URL = "https://dapp-scanning.api.cx.metamask.io";
|
10
11
|
export declare const PHISHING_DETECTION_SCAN_ENDPOINT = "scan";
|
12
|
+
export declare const PHISHING_DETECTION_BULK_SCAN_ENDPOINT = "bulk-scan";
|
11
13
|
export declare const C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL: number;
|
12
14
|
export declare const HOTLIST_REFRESH_INTERVAL: number;
|
13
15
|
export declare const STALELIST_REFRESH_INTERVAL: number;
|
@@ -151,19 +153,24 @@ export type PhishingControllerState = {
|
|
151
153
|
hotlistLastFetched: number;
|
152
154
|
stalelistLastFetched: number;
|
153
155
|
c2DomainBlocklistLastFetched: number;
|
156
|
+
urlScanCache: Record<string, UrlScanCacheEntry>;
|
154
157
|
};
|
155
158
|
/**
|
156
|
-
*
|
159
|
+
* PhishingControllerOptions
|
157
160
|
*
|
158
161
|
* Phishing controller options
|
159
|
-
*
|
160
|
-
*
|
161
|
-
*
|
162
|
+
* stalelistRefreshInterval - Polling interval used to fetch stale list.
|
163
|
+
* hotlistRefreshInterval - Polling interval used to fetch hotlist diff list.
|
164
|
+
* c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.
|
165
|
+
* urlScanCacheTTL - Time to live in seconds for cached scan results.
|
166
|
+
* urlScanCacheMaxSize - Maximum number of entries in the scan cache.
|
162
167
|
*/
|
163
168
|
export type PhishingControllerOptions = {
|
164
169
|
stalelistRefreshInterval?: number;
|
165
170
|
hotlistRefreshInterval?: number;
|
166
171
|
c2DomainBlocklistRefreshInterval?: number;
|
172
|
+
urlScanCacheTTL?: number;
|
173
|
+
urlScanCacheMaxSize?: number;
|
167
174
|
messenger: PhishingControllerMessenger;
|
168
175
|
state?: Partial<PhishingControllerState>;
|
169
176
|
};
|
@@ -180,6 +187,18 @@ export type PhishingControllerActions = PhishingControllerGetStateAction | Maybe
|
|
180
187
|
export type PhishingControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, PhishingControllerState>;
|
181
188
|
export type PhishingControllerEvents = PhishingControllerStateChangeEvent;
|
182
189
|
export type PhishingControllerMessenger = RestrictedMessenger<typeof controllerName, PhishingControllerActions, PhishingControllerEvents, never, never>;
|
190
|
+
/**
|
191
|
+
* BulkPhishingDetectionScanResponse
|
192
|
+
*
|
193
|
+
* Response for bulk phishing detection scan requests
|
194
|
+
* results - Record of domain names and their corresponding phishing detection scan results
|
195
|
+
*
|
196
|
+
* errors - Record of domain names and their corresponding errors
|
197
|
+
*/
|
198
|
+
export type BulkPhishingDetectionScanResponse = {
|
199
|
+
results: Record<string, PhishingDetectionScanResult>;
|
200
|
+
errors: Record<string, string[]>;
|
201
|
+
};
|
183
202
|
/**
|
184
203
|
* Controller that manages community-maintained lists of approved and unapproved website origins.
|
185
204
|
*/
|
@@ -192,10 +211,12 @@ export declare class PhishingController extends BaseController<typeof controller
|
|
192
211
|
* @param config.stalelistRefreshInterval - Polling interval used to fetch stale list.
|
193
212
|
* @param config.hotlistRefreshInterval - Polling interval used to fetch hotlist diff list.
|
194
213
|
* @param config.c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.
|
214
|
+
* @param config.urlScanCacheTTL - Time to live in seconds for cached scan results.
|
215
|
+
* @param config.urlScanCacheMaxSize - Maximum number of entries in the scan cache.
|
195
216
|
* @param config.messenger - The controller restricted messenger.
|
196
217
|
* @param config.state - Initial state to set on this controller.
|
197
218
|
*/
|
198
|
-
constructor({ stalelistRefreshInterval, hotlistRefreshInterval, c2DomainBlocklistRefreshInterval, messenger, state, }: PhishingControllerOptions);
|
219
|
+
constructor({ stalelistRefreshInterval, hotlistRefreshInterval, c2DomainBlocklistRefreshInterval, urlScanCacheTTL, urlScanCacheMaxSize, messenger, state, }: PhishingControllerOptions);
|
199
220
|
/**
|
200
221
|
* Updates this.detector with an instance of PhishingDetector using the current state.
|
201
222
|
*/
|
@@ -224,6 +245,22 @@ export declare class PhishingController extends BaseController<typeof controller
|
|
224
245
|
* @param interval - the new interval, in ms.
|
225
246
|
*/
|
226
247
|
setC2DomainBlocklistRefreshInterval(interval: number): void;
|
248
|
+
/**
|
249
|
+
* Set the time-to-live for URL scan cache entries.
|
250
|
+
*
|
251
|
+
* @param ttl - The TTL in seconds.
|
252
|
+
*/
|
253
|
+
setUrlScanCacheTTL(ttl: number): void;
|
254
|
+
/**
|
255
|
+
* Set the maximum number of entries in the URL scan cache.
|
256
|
+
*
|
257
|
+
* @param maxSize - The maximum cache size.
|
258
|
+
*/
|
259
|
+
setUrlScanCacheMaxSize(maxSize: number): void;
|
260
|
+
/**
|
261
|
+
* Clear the URL scan cache.
|
262
|
+
*/
|
263
|
+
clearUrlScanCache(): void;
|
227
264
|
/**
|
228
265
|
* Determine if an update to the stalelist configuration is needed.
|
229
266
|
*
|
@@ -308,6 +345,14 @@ export declare class PhishingController extends BaseController<typeof controller
|
|
308
345
|
* @returns The phishing detection scan result.
|
309
346
|
*/
|
310
347
|
scanUrl: (url: string) => Promise<PhishingDetectionScanResult>;
|
348
|
+
/**
|
349
|
+
* Scan multiple URLs for phishing in bulk. It will only scan the hostnames of the URLs.
|
350
|
+
* It also only supports web URLs.
|
351
|
+
*
|
352
|
+
* @param urls - The URLs to scan.
|
353
|
+
* @returns A mapping of URLs to their phishing detection scan results and errors.
|
354
|
+
*/
|
355
|
+
bulkScanUrls: (urls: string[]) => Promise<BulkPhishingDetectionScanResponse>;
|
311
356
|
}
|
312
357
|
export default PhishingController;
|
313
358
|
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,EACpB,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAQ3D,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EAEjC,oBAAgB;
|
1
|
+
{"version":3,"file":"PhishingController.d.cts","sourceRoot":"","sources":["../src/PhishingController.ts"],"names":[],"mappings":"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"}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import type { ControllerGetStateAction, ControllerStateChangeEvent, RestrictedMessenger } from "@metamask/base-controller";
|
2
2
|
import { BaseController } from "@metamask/base-controller";
|
3
3
|
import { type PhishingDetectorResult, type PhishingDetectionScanResult } from "./types.mjs";
|
4
|
+
import { type UrlScanCacheEntry } from "./UrlScanCache.mjs";
|
4
5
|
export declare const PHISHING_CONFIG_BASE_URL = "https://phishing-detection.api.cx.metamask.io";
|
5
6
|
export declare const METAMASK_STALELIST_FILE = "/v1/stalelist";
|
6
7
|
export declare const METAMASK_HOTLIST_DIFF_FILE = "/v1/diffsSince";
|
@@ -8,6 +9,7 @@ export declare const CLIENT_SIDE_DETECION_BASE_URL = "https://client-side-detect
|
|
8
9
|
export declare const C2_DOMAIN_BLOCKLIST_ENDPOINT = "/v1/request-blocklist";
|
9
10
|
export declare const PHISHING_DETECTION_BASE_URL = "https://dapp-scanning.api.cx.metamask.io";
|
10
11
|
export declare const PHISHING_DETECTION_SCAN_ENDPOINT = "scan";
|
12
|
+
export declare const PHISHING_DETECTION_BULK_SCAN_ENDPOINT = "bulk-scan";
|
11
13
|
export declare const C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL: number;
|
12
14
|
export declare const HOTLIST_REFRESH_INTERVAL: number;
|
13
15
|
export declare const STALELIST_REFRESH_INTERVAL: number;
|
@@ -151,19 +153,24 @@ export type PhishingControllerState = {
|
|
151
153
|
hotlistLastFetched: number;
|
152
154
|
stalelistLastFetched: number;
|
153
155
|
c2DomainBlocklistLastFetched: number;
|
156
|
+
urlScanCache: Record<string, UrlScanCacheEntry>;
|
154
157
|
};
|
155
158
|
/**
|
156
|
-
*
|
159
|
+
* PhishingControllerOptions
|
157
160
|
*
|
158
161
|
* Phishing controller options
|
159
|
-
*
|
160
|
-
*
|
161
|
-
*
|
162
|
+
* stalelistRefreshInterval - Polling interval used to fetch stale list.
|
163
|
+
* hotlistRefreshInterval - Polling interval used to fetch hotlist diff list.
|
164
|
+
* c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.
|
165
|
+
* urlScanCacheTTL - Time to live in seconds for cached scan results.
|
166
|
+
* urlScanCacheMaxSize - Maximum number of entries in the scan cache.
|
162
167
|
*/
|
163
168
|
export type PhishingControllerOptions = {
|
164
169
|
stalelistRefreshInterval?: number;
|
165
170
|
hotlistRefreshInterval?: number;
|
166
171
|
c2DomainBlocklistRefreshInterval?: number;
|
172
|
+
urlScanCacheTTL?: number;
|
173
|
+
urlScanCacheMaxSize?: number;
|
167
174
|
messenger: PhishingControllerMessenger;
|
168
175
|
state?: Partial<PhishingControllerState>;
|
169
176
|
};
|
@@ -180,6 +187,18 @@ export type PhishingControllerActions = PhishingControllerGetStateAction | Maybe
|
|
180
187
|
export type PhishingControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, PhishingControllerState>;
|
181
188
|
export type PhishingControllerEvents = PhishingControllerStateChangeEvent;
|
182
189
|
export type PhishingControllerMessenger = RestrictedMessenger<typeof controllerName, PhishingControllerActions, PhishingControllerEvents, never, never>;
|
190
|
+
/**
|
191
|
+
* BulkPhishingDetectionScanResponse
|
192
|
+
*
|
193
|
+
* Response for bulk phishing detection scan requests
|
194
|
+
* results - Record of domain names and their corresponding phishing detection scan results
|
195
|
+
*
|
196
|
+
* errors - Record of domain names and their corresponding errors
|
197
|
+
*/
|
198
|
+
export type BulkPhishingDetectionScanResponse = {
|
199
|
+
results: Record<string, PhishingDetectionScanResult>;
|
200
|
+
errors: Record<string, string[]>;
|
201
|
+
};
|
183
202
|
/**
|
184
203
|
* Controller that manages community-maintained lists of approved and unapproved website origins.
|
185
204
|
*/
|
@@ -192,10 +211,12 @@ export declare class PhishingController extends BaseController<typeof controller
|
|
192
211
|
* @param config.stalelistRefreshInterval - Polling interval used to fetch stale list.
|
193
212
|
* @param config.hotlistRefreshInterval - Polling interval used to fetch hotlist diff list.
|
194
213
|
* @param config.c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.
|
214
|
+
* @param config.urlScanCacheTTL - Time to live in seconds for cached scan results.
|
215
|
+
* @param config.urlScanCacheMaxSize - Maximum number of entries in the scan cache.
|
195
216
|
* @param config.messenger - The controller restricted messenger.
|
196
217
|
* @param config.state - Initial state to set on this controller.
|
197
218
|
*/
|
198
|
-
constructor({ stalelistRefreshInterval, hotlistRefreshInterval, c2DomainBlocklistRefreshInterval, messenger, state, }: PhishingControllerOptions);
|
219
|
+
constructor({ stalelistRefreshInterval, hotlistRefreshInterval, c2DomainBlocklistRefreshInterval, urlScanCacheTTL, urlScanCacheMaxSize, messenger, state, }: PhishingControllerOptions);
|
199
220
|
/**
|
200
221
|
* Updates this.detector with an instance of PhishingDetector using the current state.
|
201
222
|
*/
|
@@ -224,6 +245,22 @@ export declare class PhishingController extends BaseController<typeof controller
|
|
224
245
|
* @param interval - the new interval, in ms.
|
225
246
|
*/
|
226
247
|
setC2DomainBlocklistRefreshInterval(interval: number): void;
|
248
|
+
/**
|
249
|
+
* Set the time-to-live for URL scan cache entries.
|
250
|
+
*
|
251
|
+
* @param ttl - The TTL in seconds.
|
252
|
+
*/
|
253
|
+
setUrlScanCacheTTL(ttl: number): void;
|
254
|
+
/**
|
255
|
+
* Set the maximum number of entries in the URL scan cache.
|
256
|
+
*
|
257
|
+
* @param maxSize - The maximum cache size.
|
258
|
+
*/
|
259
|
+
setUrlScanCacheMaxSize(maxSize: number): void;
|
260
|
+
/**
|
261
|
+
* Clear the URL scan cache.
|
262
|
+
*/
|
263
|
+
clearUrlScanCache(): void;
|
227
264
|
/**
|
228
265
|
* Determine if an update to the stalelist configuration is needed.
|
229
266
|
*
|
@@ -308,6 +345,14 @@ export declare class PhishingController extends BaseController<typeof controller
|
|
308
345
|
* @returns The phishing detection scan result.
|
309
346
|
*/
|
310
347
|
scanUrl: (url: string) => Promise<PhishingDetectionScanResult>;
|
348
|
+
/**
|
349
|
+
* Scan multiple URLs for phishing in bulk. It will only scan the hostnames of the URLs.
|
350
|
+
* It also only supports web URLs.
|
351
|
+
*
|
352
|
+
* @param urls - The URLs to scan.
|
353
|
+
* @returns A mapping of URLs to their phishing detection scan results and errors.
|
354
|
+
*/
|
355
|
+
bulkScanUrls: (urls: string[]) => Promise<BulkPhishingDetectionScanResponse>;
|
311
356
|
}
|
312
357
|
export default PhishingController;
|
313
358
|
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,EACpB,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAQ3D,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,2BAA2B,EAEjC,oBAAgB;
|
1
|
+
{"version":3,"file":"PhishingController.d.mts","sourceRoot":"","sources":["../src/PhishingController.ts"],"names":[],"mappings":"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"}
|
@@ -9,13 +9,14 @@ 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_inProgressHotlistUpdate, _PhishingController_inProgressStalelistUpdate, _PhishingController_isProgressC2DomainBlocklistUpdate, _PhishingController_registerMessageHandlers, _PhishingController_updateStalelist, _PhishingController_updateHotlist, _PhishingController_updateC2DomainBlocklist, _PhishingController_queryConfig;
|
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;
|
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
17
|
import { PhishingDetector } from "./PhishingDetector.mjs";
|
18
18
|
import { PhishingDetectorResultType, RecommendedAction } from "./types.mjs";
|
19
|
+
import { DEFAULT_URL_SCAN_CACHE_MAX_SIZE, DEFAULT_URL_SCAN_CACHE_TTL, UrlScanCache } from "./UrlScanCache.mjs";
|
19
20
|
import { applyDiffs, fetchTimeNow, getHostnameFromUrl, roundToNearestMinute, getHostnameFromWebUrl } from "./utils.mjs";
|
20
21
|
export const PHISHING_CONFIG_BASE_URL = 'https://phishing-detection.api.cx.metamask.io';
|
21
22
|
export const METAMASK_STALELIST_FILE = '/v1/stalelist';
|
@@ -24,6 +25,7 @@ export const CLIENT_SIDE_DETECION_BASE_URL = 'https://client-side-detection.api.
|
|
24
25
|
export const C2_DOMAIN_BLOCKLIST_ENDPOINT = '/v1/request-blocklist';
|
25
26
|
export const PHISHING_DETECTION_BASE_URL = 'https://dapp-scanning.api.cx.metamask.io';
|
26
27
|
export const PHISHING_DETECTION_SCAN_ENDPOINT = 'scan';
|
28
|
+
export const PHISHING_DETECTION_BULK_SCAN_ENDPOINT = 'bulk-scan';
|
27
29
|
export const C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL = 5 * 60; // 5 mins in seconds
|
28
30
|
export const HOTLIST_REFRESH_INTERVAL = 5 * 60; // 5 mins in seconds
|
29
31
|
export const STALELIST_REFRESH_INTERVAL = 30 * 24 * 60 * 60; // 30 days in seconds
|
@@ -66,6 +68,7 @@ const metadata = {
|
|
66
68
|
hotlistLastFetched: { persist: true, anonymous: false },
|
67
69
|
stalelistLastFetched: { persist: true, anonymous: false },
|
68
70
|
c2DomainBlocklistLastFetched: { persist: true, anonymous: false },
|
71
|
+
urlScanCache: { persist: true, anonymous: false },
|
69
72
|
};
|
70
73
|
/**
|
71
74
|
* Get a default empty state for the controller.
|
@@ -78,6 +81,7 @@ const getDefaultState = () => {
|
|
78
81
|
hotlistLastFetched: 0,
|
79
82
|
stalelistLastFetched: 0,
|
80
83
|
c2DomainBlocklistLastFetched: 0,
|
84
|
+
urlScanCache: {},
|
81
85
|
};
|
82
86
|
};
|
83
87
|
/**
|
@@ -91,10 +95,12 @@ export class PhishingController extends BaseController {
|
|
91
95
|
* @param config.stalelistRefreshInterval - Polling interval used to fetch stale list.
|
92
96
|
* @param config.hotlistRefreshInterval - Polling interval used to fetch hotlist diff list.
|
93
97
|
* @param config.c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.
|
98
|
+
* @param config.urlScanCacheTTL - Time to live in seconds for cached scan results.
|
99
|
+
* @param config.urlScanCacheMaxSize - Maximum number of entries in the scan cache.
|
94
100
|
* @param config.messenger - The controller restricted messenger.
|
95
101
|
* @param config.state - Initial state to set on this controller.
|
96
102
|
*/
|
97
|
-
constructor({ stalelistRefreshInterval = STALELIST_REFRESH_INTERVAL, hotlistRefreshInterval = HOTLIST_REFRESH_INTERVAL, c2DomainBlocklistRefreshInterval = C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL, messenger, state = {}, }) {
|
103
|
+
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 = {}, }) {
|
98
104
|
super({
|
99
105
|
name: controllerName,
|
100
106
|
metadata,
|
@@ -111,6 +117,7 @@ export class PhishingController extends BaseController {
|
|
111
117
|
_PhishingController_stalelistRefreshInterval.set(this, void 0);
|
112
118
|
_PhishingController_hotlistRefreshInterval.set(this, void 0);
|
113
119
|
_PhishingController_c2DomainBlocklistRefreshInterval.set(this, void 0);
|
120
|
+
_PhishingController_urlScanCache.set(this, void 0);
|
114
121
|
_PhishingController_inProgressHotlistUpdate.set(this, void 0);
|
115
122
|
_PhishingController_inProgressStalelistUpdate.set(this, void 0);
|
116
123
|
_PhishingController_isProgressC2DomainBlocklistUpdate.set(this, void 0);
|
@@ -130,6 +137,10 @@ export class PhishingController extends BaseController {
|
|
130
137
|
fetchError: 'url is not a valid web URL',
|
131
138
|
};
|
132
139
|
}
|
140
|
+
const cachedResult = __classPrivateFieldGet(this, _PhishingController_urlScanCache, "f").get(hostname);
|
141
|
+
if (cachedResult) {
|
142
|
+
return cachedResult;
|
143
|
+
}
|
133
144
|
const apiResponse = await safelyExecuteWithTimeout(async () => {
|
134
145
|
const res = await fetch(`${PHISHING_DETECTION_BASE_URL}/${PHISHING_DETECTION_SCAN_ENDPOINT}?url=${encodeURIComponent(hostname)}`, {
|
135
146
|
method: 'GET',
|
@@ -160,14 +171,163 @@ export class PhishingController extends BaseController {
|
|
160
171
|
fetchError: apiResponse.error,
|
161
172
|
};
|
162
173
|
}
|
163
|
-
|
174
|
+
const result = {
|
164
175
|
domainName: hostname,
|
165
176
|
recommendedAction: apiResponse.recommendedAction,
|
166
177
|
};
|
178
|
+
__classPrivateFieldGet(this, _PhishingController_urlScanCache, "f").add(hostname, result);
|
179
|
+
return result;
|
180
|
+
};
|
181
|
+
/**
|
182
|
+
* Scan multiple URLs for phishing in bulk. It will only scan the hostnames of the URLs.
|
183
|
+
* It also only supports web URLs.
|
184
|
+
*
|
185
|
+
* @param urls - The URLs to scan.
|
186
|
+
* @returns A mapping of URLs to their phishing detection scan results and errors.
|
187
|
+
*/
|
188
|
+
this.bulkScanUrls = async (urls) => {
|
189
|
+
if (!urls || urls.length === 0) {
|
190
|
+
return {
|
191
|
+
results: {},
|
192
|
+
errors: {},
|
193
|
+
};
|
194
|
+
}
|
195
|
+
// we are arbitrarily limiting the number of URLs to 250
|
196
|
+
const MAX_TOTAL_URLS = 250;
|
197
|
+
if (urls.length > MAX_TOTAL_URLS) {
|
198
|
+
return {
|
199
|
+
results: {},
|
200
|
+
errors: {
|
201
|
+
too_many_urls: [
|
202
|
+
`Maximum of ${MAX_TOTAL_URLS} URLs allowed per request`,
|
203
|
+
],
|
204
|
+
},
|
205
|
+
};
|
206
|
+
}
|
207
|
+
const MAX_URL_LENGTH = 2048;
|
208
|
+
const combinedResponse = {
|
209
|
+
results: {},
|
210
|
+
errors: {},
|
211
|
+
};
|
212
|
+
// Extract hostnames from URLs and check for validity and length constraints
|
213
|
+
const urlsToHostnames = {};
|
214
|
+
const urlsToFetch = [];
|
215
|
+
for (const url of urls) {
|
216
|
+
if (url.length > MAX_URL_LENGTH) {
|
217
|
+
combinedResponse.errors[url] = [
|
218
|
+
`URL length must not exceed ${MAX_URL_LENGTH} characters`,
|
219
|
+
];
|
220
|
+
continue;
|
221
|
+
}
|
222
|
+
const [hostname, ok] = getHostnameFromWebUrl(url);
|
223
|
+
if (!ok) {
|
224
|
+
combinedResponse.errors[url] = ['url is not a valid web URL'];
|
225
|
+
continue;
|
226
|
+
}
|
227
|
+
// Check if result is already in cache
|
228
|
+
const cachedResult = __classPrivateFieldGet(this, _PhishingController_urlScanCache, "f").get(hostname);
|
229
|
+
if (cachedResult) {
|
230
|
+
// Use cached result
|
231
|
+
combinedResponse.results[url] = cachedResult;
|
232
|
+
}
|
233
|
+
else {
|
234
|
+
// Add to list of URLs to fetch
|
235
|
+
urlsToHostnames[url] = hostname;
|
236
|
+
urlsToFetch.push(url);
|
237
|
+
}
|
238
|
+
}
|
239
|
+
// If there are URLs to fetch, process them in batches
|
240
|
+
if (urlsToFetch.length > 0) {
|
241
|
+
// The API has a limit of 50 URLs per request, so we batch the requests
|
242
|
+
const MAX_URLS_PER_BATCH = 50;
|
243
|
+
const batches = [];
|
244
|
+
for (let i = 0; i < urlsToFetch.length; i += MAX_URLS_PER_BATCH) {
|
245
|
+
batches.push(urlsToFetch.slice(i, i + MAX_URLS_PER_BATCH));
|
246
|
+
}
|
247
|
+
// Process each batch in parallel
|
248
|
+
const batchResults = await Promise.all(batches.map((batchUrls) => __classPrivateFieldGet(this, _PhishingController_processBatch, "f").call(this, batchUrls)));
|
249
|
+
// Merge results and errors from all batches
|
250
|
+
batchResults.forEach((batchResponse) => {
|
251
|
+
// Add results to cache and combine with response
|
252
|
+
Object.entries(batchResponse.results).forEach(([url, result]) => {
|
253
|
+
const hostname = urlsToHostnames[url];
|
254
|
+
if (hostname) {
|
255
|
+
__classPrivateFieldGet(this, _PhishingController_urlScanCache, "f").add(hostname, result);
|
256
|
+
}
|
257
|
+
combinedResponse.results[url] = result;
|
258
|
+
});
|
259
|
+
// Combine errors
|
260
|
+
Object.entries(batchResponse.errors).forEach(([key, messages]) => {
|
261
|
+
combinedResponse.errors[key] = [
|
262
|
+
...(combinedResponse.errors[key] || []),
|
263
|
+
...messages,
|
264
|
+
];
|
265
|
+
});
|
266
|
+
});
|
267
|
+
}
|
268
|
+
return combinedResponse;
|
167
269
|
};
|
270
|
+
/**
|
271
|
+
* Process a batch of URLs (up to 50) for phishing detection.
|
272
|
+
*
|
273
|
+
* @param urls - A batch of URLs to scan.
|
274
|
+
* @returns The scan results and errors for this batch.
|
275
|
+
*/
|
276
|
+
_PhishingController_processBatch.set(this, async (urls) => {
|
277
|
+
const apiResponse = await safelyExecuteWithTimeout(async () => {
|
278
|
+
const res = await fetch(`${PHISHING_DETECTION_BASE_URL}/${PHISHING_DETECTION_BULK_SCAN_ENDPOINT}`, {
|
279
|
+
method: 'POST',
|
280
|
+
headers: {
|
281
|
+
Accept: 'application/json',
|
282
|
+
'Content-Type': 'application/json',
|
283
|
+
},
|
284
|
+
body: JSON.stringify({ urls }),
|
285
|
+
});
|
286
|
+
if (!res.ok) {
|
287
|
+
return {
|
288
|
+
error: `${res.status} ${res.statusText}`,
|
289
|
+
status: res.status,
|
290
|
+
statusText: res.statusText,
|
291
|
+
};
|
292
|
+
}
|
293
|
+
const data = await res.json();
|
294
|
+
return data;
|
295
|
+
}, true, 15000);
|
296
|
+
// Handle timeout or network errors
|
297
|
+
if (!apiResponse) {
|
298
|
+
return {
|
299
|
+
results: {},
|
300
|
+
errors: {
|
301
|
+
network_error: ['timeout of 15000ms exceeded'],
|
302
|
+
},
|
303
|
+
};
|
304
|
+
}
|
305
|
+
// Handle HTTP error responses
|
306
|
+
if ('error' in apiResponse &&
|
307
|
+
'status' in apiResponse &&
|
308
|
+
'statusText' in apiResponse) {
|
309
|
+
return {
|
310
|
+
results: {},
|
311
|
+
errors: {
|
312
|
+
api_error: [`${apiResponse.status} ${apiResponse.statusText}`],
|
313
|
+
},
|
314
|
+
};
|
315
|
+
}
|
316
|
+
return apiResponse;
|
317
|
+
});
|
168
318
|
__classPrivateFieldSet(this, _PhishingController_stalelistRefreshInterval, stalelistRefreshInterval, "f");
|
169
319
|
__classPrivateFieldSet(this, _PhishingController_hotlistRefreshInterval, hotlistRefreshInterval, "f");
|
170
320
|
__classPrivateFieldSet(this, _PhishingController_c2DomainBlocklistRefreshInterval, c2DomainBlocklistRefreshInterval, "f");
|
321
|
+
__classPrivateFieldSet(this, _PhishingController_urlScanCache, new UrlScanCache({
|
322
|
+
cacheTTL: urlScanCacheTTL,
|
323
|
+
maxCacheSize: urlScanCacheMaxSize,
|
324
|
+
initialCache: this.state.urlScanCache,
|
325
|
+
updateState: (cache) => {
|
326
|
+
this.update((draftState) => {
|
327
|
+
draftState.urlScanCache = cache;
|
328
|
+
});
|
329
|
+
},
|
330
|
+
}), "f");
|
171
331
|
__classPrivateFieldGet(this, _PhishingController_instances, "m", _PhishingController_registerMessageHandlers).call(this);
|
172
332
|
this.updatePhishingDetector();
|
173
333
|
}
|
@@ -207,6 +367,28 @@ export class PhishingController extends BaseController {
|
|
207
367
|
setC2DomainBlocklistRefreshInterval(interval) {
|
208
368
|
__classPrivateFieldSet(this, _PhishingController_c2DomainBlocklistRefreshInterval, interval, "f");
|
209
369
|
}
|
370
|
+
/**
|
371
|
+
* Set the time-to-live for URL scan cache entries.
|
372
|
+
*
|
373
|
+
* @param ttl - The TTL in seconds.
|
374
|
+
*/
|
375
|
+
setUrlScanCacheTTL(ttl) {
|
376
|
+
__classPrivateFieldGet(this, _PhishingController_urlScanCache, "f").setTTL(ttl);
|
377
|
+
}
|
378
|
+
/**
|
379
|
+
* Set the maximum number of entries in the URL scan cache.
|
380
|
+
*
|
381
|
+
* @param maxSize - The maximum cache size.
|
382
|
+
*/
|
383
|
+
setUrlScanCacheMaxSize(maxSize) {
|
384
|
+
__classPrivateFieldGet(this, _PhishingController_urlScanCache, "f").setMaxSize(maxSize);
|
385
|
+
}
|
386
|
+
/**
|
387
|
+
* Clear the URL scan cache.
|
388
|
+
*/
|
389
|
+
clearUrlScanCache() {
|
390
|
+
__classPrivateFieldGet(this, _PhishingController_urlScanCache, "f").clear();
|
391
|
+
}
|
210
392
|
/**
|
211
393
|
* Determine if an update to the stalelist configuration is needed.
|
212
394
|
*
|
@@ -367,7 +549,7 @@ export class PhishingController extends BaseController {
|
|
367
549
|
}
|
368
550
|
}
|
369
551
|
}
|
370
|
-
_PhishingController_detector = new WeakMap(), _PhishingController_stalelistRefreshInterval = new WeakMap(), _PhishingController_hotlistRefreshInterval = new WeakMap(), _PhishingController_c2DomainBlocklistRefreshInterval = new WeakMap(), _PhishingController_inProgressHotlistUpdate = new WeakMap(), _PhishingController_inProgressStalelistUpdate = new WeakMap(), _PhishingController_isProgressC2DomainBlocklistUpdate = new WeakMap(), _PhishingController_instances = new WeakSet(), _PhishingController_registerMessageHandlers = function _PhishingController_registerMessageHandlers() {
|
552
|
+
_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(), _PhishingController_registerMessageHandlers = function _PhishingController_registerMessageHandlers() {
|
371
553
|
this.messagingSystem.registerActionHandler(`${controllerName}:maybeUpdateState`, this.maybeUpdateState.bind(this));
|
372
554
|
this.messagingSystem.registerActionHandler(`${controllerName}:testOrigin`, this.test.bind(this));
|
373
555
|
}, _PhishingController_updateStalelist =
|
@@ -408,7 +590,6 @@ async function _PhishingController_updateStalelist() {
|
|
408
590
|
return;
|
409
591
|
}
|
410
592
|
// TODO: Either fix this lint violation or explain why it's necessary to ignore.
|
411
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
412
593
|
const { eth_phishing_detect_config, ...partialState } = stalelistResponse.data;
|
413
594
|
const metamaskListState = {
|
414
595
|
...eth_phishing_detect_config,
|