@metamask-previews/phishing-controller 12.3.2-preview-def92ff7 → 12.4.0-preview-4a9b4a93
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 +15 -1
- package/dist/PhishingController.cjs +54 -1
- package/dist/PhishingController.cjs.map +1 -1
- package/dist/PhishingController.d.cts +11 -1
- package/dist/PhishingController.d.cts.map +1 -1
- package/dist/PhishingController.d.mts +11 -1
- package/dist/PhishingController.d.mts.map +1 -1
- package/dist/PhishingController.mjs +56 -3
- package/dist/PhishingController.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/types.cjs +19 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +42 -0
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +42 -0
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs +18 -0
- package/dist/types.mjs.map +1 -1
- package/dist/utils.cjs +27 -2
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +13 -0
- package/dist/utils.d.cts.map +1 -1
- package/dist/utils.d.mts +13 -0
- package/dist/utils.d.mts.map +1 -1
- package/dist/utils.mjs +25 -1
- package/dist/utils.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PhishingController.mjs","sourceRoot":"","sources":["../src/PhishingController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { safelyExecute } from '@metamask/controller-utils';\nimport { toASCII } from 'punycode/punycode.js';\n\nimport { PhishingDetector } from './PhishingDetector';\nimport {\n PhishingDetectorResultType,\n type PhishingDetectorResult,\n} from './types';\nimport {\n applyDiffs,\n fetchTimeNow,\n getHostnameFromUrl,\n roundToNearestMinute,\n} from './utils';\n\nexport const PHISHING_CONFIG_BASE_URL =\n 'https://phishing-detection.api.cx.metamask.io';\nexport const METAMASK_STALELIST_FILE = '/v1/stalelist';\nexport const METAMASK_HOTLIST_DIFF_FILE = '/v1/diffsSince';\n\nexport const CLIENT_SIDE_DETECION_BASE_URL =\n 'https://client-side-detection.api.cx.metamask.io';\nexport const C2_DOMAIN_BLOCKLIST_ENDPOINT = '/v1/request-blocklist';\n\nexport const C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL = 5 * 60; // 5 mins in seconds\nexport const HOTLIST_REFRESH_INTERVAL = 5 * 60; // 5 mins in seconds\nexport const STALELIST_REFRESH_INTERVAL = 30 * 24 * 60 * 60; // 30 days in seconds\n\nexport const METAMASK_STALELIST_URL = `${PHISHING_CONFIG_BASE_URL}${METAMASK_STALELIST_FILE}`;\nexport const METAMASK_HOTLIST_DIFF_URL = `${PHISHING_CONFIG_BASE_URL}${METAMASK_HOTLIST_DIFF_FILE}`;\nexport const C2_DOMAIN_BLOCKLIST_URL = `${CLIENT_SIDE_DETECION_BASE_URL}${C2_DOMAIN_BLOCKLIST_ENDPOINT}`;\n\n/**\n * @type ListTypes\n *\n * Type outlining the types of lists provided by aggregating different source lists\n */\nexport type ListTypes =\n | 'fuzzylist'\n | 'blocklist'\n | 'allowlist'\n | 'c2DomainBlocklist';\n\n/**\n * @type EthPhishingResponse\n *\n * Configuration response from the eth-phishing-detect package\n * consisting of approved and unapproved website origins\n * @property blacklist - List of unapproved origins\n * @property fuzzylist - List of fuzzy-matched unapproved origins\n * @property tolerance - Fuzzy match tolerance level\n * @property version - Version number of this configuration\n * @property whitelist - List of approved origins\n */\nexport type EthPhishingResponse = {\n blacklist: string[];\n fuzzylist: string[];\n tolerance: number;\n version: number;\n whitelist: string[];\n};\n\n/**\n * @type C2DomainBlocklistResponse\n *\n * Response for blocklist update requests\n * @property recentlyAdded - List of c2 domains recently added to the blocklist\n * @property recentlyRemoved - List of c2 domains recently removed from the blocklist\n * @property lastFetchedAt - Timestamp of the last fetch request\n */\nexport type C2DomainBlocklistResponse = {\n recentlyAdded: string[];\n recentlyRemoved: string[];\n lastFetchedAt: string;\n};\n\n/**\n * @type PhishingStalelist\n *\n * type defining expected type of the stalelist.json file.\n * @property eth_phishing_detect_config - Stale list sourced from eth-phishing-detect's config.json.\n * @property tolerance - Fuzzy match tolerance level\n * @property lastUpdated - Timestamp of last update.\n * @property version - Stalelist data structure iteration.\n */\nexport type PhishingStalelist = {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n eth_phishing_detect_config: Record<ListTypes, string[]>;\n tolerance: number;\n version: number;\n lastUpdated: number;\n};\n\n/**\n * @type PhishingListState\n *\n * type defining the persisted list state. This is the persisted state that is updated frequently with `this.maybeUpdateState()`.\n * @property allowlist - List of approved origins (legacy naming \"whitelist\")\n * @property blocklist - List of unapproved origins (legacy naming \"blacklist\")\n * @property c2DomainBlocklist - List of hashed hostnames that C2 requests are blocked against.\n * @property fuzzylist - List of fuzzy-matched unapproved origins\n * @property tolerance - Fuzzy match tolerance level\n * @property lastUpdated - Timestamp of last update.\n * @property version - Version of the phishing list state.\n * @property name - Name of the list. Used for attribution.\n */\nexport type PhishingListState = {\n allowlist: string[];\n blocklist: string[];\n c2DomainBlocklist: string[];\n fuzzylist: string[];\n tolerance: number;\n version: number;\n lastUpdated: number;\n name: ListNames;\n};\n\n/**\n * @type HotlistDiff\n *\n * type defining the expected type of the diffs in hotlist.json file.\n * @property url - Url of the diff entry.\n * @property timestamp - Timestamp at which the diff was identified.\n * @property targetList - The list name where the diff was identified.\n * @property isRemoval - Was the diff identified a removal type.\n */\nexport type HotlistDiff = {\n url: string;\n timestamp: number;\n targetList: `${ListKeys}.${ListTypes}`;\n isRemoval?: boolean;\n};\n\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type DataResultWrapper<T> = {\n data: T;\n};\n\n/**\n * @type Hotlist\n *\n * Type defining expected hotlist.json file.\n * @property url - Url of the diff entry.\n * @property timestamp - Timestamp at which the diff was identified.\n * @property targetList - The list name where the diff was identified.\n * @property isRemoval - Was the diff identified a removal type.\n */\nexport type Hotlist = HotlistDiff[];\n\n/**\n * Enum containing upstream data provider source list keys.\n * These are the keys denoting lists consumed by the upstream data provider.\n */\nexport enum ListKeys {\n EthPhishingDetectConfig = 'eth_phishing_detect_config',\n}\n\n/**\n * Enum containing downstream client attribution names.\n */\nexport enum ListNames {\n MetaMask = 'MetaMask',\n}\n\n/**\n * Maps from downstream client attribution name\n * to list key sourced from upstream data provider.\n */\nconst phishingListNameKeyMap = {\n [ListNames.MetaMask]: ListKeys.EthPhishingDetectConfig,\n};\n\n/**\n * Maps from list key sourced from upstream data\n * provider to downstream client attribution name.\n */\nexport const phishingListKeyNameMap = {\n [ListKeys.EthPhishingDetectConfig]: ListNames.MetaMask,\n};\n\nconst controllerName = 'PhishingController';\n\nconst metadata = {\n phishingLists: { persist: true, anonymous: false },\n whitelist: { persist: true, anonymous: false },\n hotlistLastFetched: { persist: true, anonymous: false },\n stalelistLastFetched: { persist: true, anonymous: false },\n c2DomainBlocklistLastFetched: { persist: true, anonymous: false },\n};\n\n/**\n * Get a default empty state for the controller.\n * @returns The default empty state.\n */\nconst getDefaultState = (): PhishingControllerState => {\n return {\n phishingLists: [],\n whitelist: [],\n hotlistLastFetched: 0,\n stalelistLastFetched: 0,\n c2DomainBlocklistLastFetched: 0,\n };\n};\n\n/**\n * @type PhishingControllerState\n *\n * Phishing controller state\n * @property phishing - eth-phishing-detect configuration\n * @property whitelist - array of temporarily-approved origins\n */\nexport type PhishingControllerState = {\n phishingLists: PhishingListState[];\n whitelist: string[];\n hotlistLastFetched: number;\n stalelistLastFetched: number;\n c2DomainBlocklistLastFetched: number;\n};\n\n/**\n * @type PhishingControllerOptions\n *\n * Phishing controller options\n * @property stalelistRefreshInterval - Polling interval used to fetch stale list.\n * @property hotlistRefreshInterval - Polling interval used to fetch hotlist diff list.\n * @property c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.\n */\nexport type PhishingControllerOptions = {\n stalelistRefreshInterval?: number;\n hotlistRefreshInterval?: number;\n c2DomainBlocklistRefreshInterval?: number;\n messenger: PhishingControllerMessenger;\n state?: Partial<PhishingControllerState>;\n};\n\nexport type MaybeUpdateState = {\n type: `${typeof controllerName}:maybeUpdateState`;\n handler: PhishingController['maybeUpdateState'];\n};\n\nexport type TestOrigin = {\n type: `${typeof controllerName}:testOrigin`;\n handler: PhishingController['test'];\n};\n\nexport type PhishingControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n PhishingControllerState\n>;\n\nexport type PhishingControllerActions =\n | PhishingControllerGetStateAction\n | MaybeUpdateState\n | TestOrigin;\n\nexport type PhishingControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n PhishingControllerState\n>;\n\nexport type PhishingControllerEvents = PhishingControllerStateChangeEvent;\n\nexport type PhishingControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n PhishingControllerActions,\n PhishingControllerEvents,\n never,\n never\n>;\n\n/**\n * Controller that manages community-maintained lists of approved and unapproved website origins.\n */\nexport class PhishingController extends BaseController<\n typeof controllerName,\n PhishingControllerState,\n PhishingControllerMessenger\n> {\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #detector: any;\n\n #stalelistRefreshInterval: number;\n\n #hotlistRefreshInterval: number;\n\n #c2DomainBlocklistRefreshInterval: number;\n\n #inProgressHotlistUpdate?: Promise<void>;\n\n #inProgressStalelistUpdate?: Promise<void>;\n\n #isProgressC2DomainBlocklistUpdate?: Promise<void>;\n\n /**\n * Construct a Phishing Controller.\n *\n * @param config - Initial options used to configure this controller.\n * @param config.stalelistRefreshInterval - Polling interval used to fetch stale list.\n * @param config.hotlistRefreshInterval - Polling interval used to fetch hotlist diff list.\n * @param config.c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.\n * @param config.messenger - The controller restricted messenger.\n * @param config.state - Initial state to set on this controller.\n */\n constructor({\n stalelistRefreshInterval = STALELIST_REFRESH_INTERVAL,\n hotlistRefreshInterval = HOTLIST_REFRESH_INTERVAL,\n c2DomainBlocklistRefreshInterval = C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL,\n messenger,\n state = {},\n }: PhishingControllerOptions) {\n super({\n name: controllerName,\n metadata,\n messenger,\n state: {\n ...getDefaultState(),\n ...state,\n },\n });\n\n this.#stalelistRefreshInterval = stalelistRefreshInterval;\n this.#hotlistRefreshInterval = hotlistRefreshInterval;\n this.#c2DomainBlocklistRefreshInterval = c2DomainBlocklistRefreshInterval;\n this.#registerMessageHandlers();\n\n this.updatePhishingDetector();\n }\n\n /**\n * Constructor helper for registering this controller's messaging system\n * actions.\n */\n #registerMessageHandlers(): void {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:maybeUpdateState` as const,\n this.maybeUpdateState.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:testOrigin` as const,\n this.test.bind(this),\n );\n }\n\n /**\n * Updates this.detector with an instance of PhishingDetector using the current state.\n */\n updatePhishingDetector() {\n this.#detector = new PhishingDetector(this.state.phishingLists);\n }\n\n /**\n * Set the interval at which the stale phishing list will be refetched.\n * Fetching will only occur on the next call to test/bypass.\n * For immediate update to the phishing list, call {@link updateStalelist} directly.\n *\n * @param interval - the new interval, in ms.\n */\n setStalelistRefreshInterval(interval: number) {\n this.#stalelistRefreshInterval = interval;\n }\n\n /**\n * Set the interval at which the hot list will be refetched.\n * Fetching will only occur on the next call to test/bypass.\n * For immediate update to the phishing list, call {@link updateHotlist} directly.\n *\n * @param interval - the new interval, in ms.\n */\n setHotlistRefreshInterval(interval: number) {\n this.#hotlistRefreshInterval = interval;\n }\n\n /**\n * Set the interval at which the C2 domain blocklist will be refetched.\n * Fetching will only occur on the next call to test/bypass.\n * For immediate update to the phishing list, call {@link updateHotlist} directly.\n *\n * @param interval - the new interval, in ms.\n */\n setC2DomainBlocklistRefreshInterval(interval: number) {\n this.#c2DomainBlocklistRefreshInterval = interval;\n }\n\n /**\n * Determine if an update to the stalelist configuration is needed.\n *\n * @returns Whether an update is needed\n */\n isStalelistOutOfDate() {\n return (\n fetchTimeNow() - this.state.stalelistLastFetched >=\n this.#stalelistRefreshInterval\n );\n }\n\n /**\n * Determine if an update to the hotlist configuration is needed.\n *\n * @returns Whether an update is needed\n */\n isHotlistOutOfDate() {\n return (\n fetchTimeNow() - this.state.hotlistLastFetched >=\n this.#hotlistRefreshInterval\n );\n }\n\n /**\n * Determine if an update to the C2 domain blocklist is needed.\n *\n * @returns Whether an update is needed\n */\n isC2DomainBlocklistOutOfDate() {\n return (\n fetchTimeNow() - this.state.c2DomainBlocklistLastFetched >=\n this.#c2DomainBlocklistRefreshInterval\n );\n }\n\n /**\n * Conditionally update the phishing configuration.\n *\n * If the stalelist configuration is out of date, this function will call `updateStalelist`\n * to update the configuration. This will automatically grab the hotlist,\n * so it isn't necessary to continue on to download the hotlist and the c2 domain blocklist.\n *\n */\n async maybeUpdateState() {\n const staleListOutOfDate = this.isStalelistOutOfDate();\n if (staleListOutOfDate) {\n await this.updateStalelist();\n return;\n }\n const hotlistOutOfDate = this.isHotlistOutOfDate();\n if (hotlistOutOfDate) {\n await this.updateHotlist();\n }\n const c2DomainBlocklistOutOfDate = this.isC2DomainBlocklistOutOfDate();\n if (c2DomainBlocklistOutOfDate) {\n await this.updateC2DomainBlocklist();\n }\n }\n\n /**\n * Determines if a given origin is unapproved.\n *\n * It is strongly recommended that you call {@link maybeUpdateState} before calling this,\n * to check whether the phishing configuration is up-to-date. It will be updated if necessary\n * by calling {@link updateStalelist} or {@link updateHotlist}.\n *\n * @param origin - Domain origin of a website.\n * @returns Whether the origin is an unapproved origin.\n */\n test(origin: string): PhishingDetectorResult {\n const punycodeOrigin = toASCII(origin);\n const hostname = getHostnameFromUrl(punycodeOrigin);\n if (this.state.whitelist.includes(hostname || punycodeOrigin)) {\n return { result: false, type: PhishingDetectorResultType.All }; // Same as whitelisted match returned by detector.check(...).\n }\n return this.#detector.check(punycodeOrigin);\n }\n\n /**\n * Checks if a request URL's domain is blocked against the request blocklist.\n *\n * This method is used to determine if a specific request URL is associated with a malicious\n * command and control (C2) domain. The URL's hostname is hashed and checked against a configured\n * blocklist of known malicious domains.\n *\n * @param origin - The full request URL to be checked.\n * @returns An object indicating whether the URL's domain is blocked and relevant metadata.\n */\n isBlockedRequest(origin: string): PhishingDetectorResult {\n const punycodeOrigin = toASCII(origin);\n const hostname = getHostnameFromUrl(punycodeOrigin);\n if (this.state.whitelist.includes(hostname || punycodeOrigin)) {\n return { result: false, type: PhishingDetectorResultType.All }; // Same as whitelisted match returned by detector.check(...).\n }\n return this.#detector.isMaliciousC2Domain(punycodeOrigin);\n }\n\n /**\n * Temporarily marks a given origin as approved.\n *\n * @param origin - The origin to mark as approved.\n */\n bypass(origin: string) {\n const punycodeOrigin = toASCII(origin);\n const hostname = getHostnameFromUrl(punycodeOrigin);\n const { whitelist } = this.state;\n if (whitelist.includes(hostname || punycodeOrigin)) {\n return;\n }\n this.update((draftState) => {\n draftState.whitelist.push(hostname || punycodeOrigin);\n });\n }\n\n /**\n * Update the C2 domain blocklist.\n *\n * If an update is in progress, no additional update will be made. Instead this will wait until\n * the in-progress update has finished.\n */\n async updateC2DomainBlocklist() {\n if (this.#isProgressC2DomainBlocklistUpdate) {\n await this.#isProgressC2DomainBlocklistUpdate;\n return;\n }\n\n try {\n this.#isProgressC2DomainBlocklistUpdate = this.#updateC2DomainBlocklist();\n await this.#isProgressC2DomainBlocklistUpdate;\n } finally {\n this.#isProgressC2DomainBlocklistUpdate = undefined;\n }\n }\n\n /**\n * Update the hotlist.\n *\n * If an update is in progress, no additional update will be made. Instead this will wait until\n * the in-progress update has finished.\n */\n async updateHotlist() {\n if (this.#inProgressHotlistUpdate) {\n await this.#inProgressHotlistUpdate;\n return;\n }\n\n try {\n this.#inProgressHotlistUpdate = this.#updateHotlist();\n await this.#inProgressHotlistUpdate;\n } finally {\n this.#inProgressHotlistUpdate = undefined;\n }\n }\n\n /**\n * Update the stalelist.\n *\n * If an update is in progress, no additional update will be made. Instead this will wait until\n * the in-progress update has finished.\n */\n async updateStalelist() {\n if (this.#inProgressStalelistUpdate) {\n await this.#inProgressStalelistUpdate;\n return;\n }\n\n try {\n this.#inProgressStalelistUpdate = this.#updateStalelist();\n await this.#inProgressStalelistUpdate;\n } finally {\n this.#inProgressStalelistUpdate = undefined;\n }\n }\n\n /**\n * Update the stalelist configuration.\n *\n * This should only be called from the `updateStalelist` function, which is a wrapper around\n * this function that prevents redundant configuration updates.\n */\n async #updateStalelist() {\n let stalelistResponse: DataResultWrapper<PhishingStalelist> | null = null;\n let hotlistDiffsResponse: DataResultWrapper<Hotlist> | null = null;\n let c2DomainBlocklistResponse: C2DomainBlocklistResponse | null = null;\n try {\n const stalelistPromise = this.#queryConfig<\n DataResultWrapper<PhishingStalelist>\n >(METAMASK_STALELIST_URL);\n\n const c2DomainBlocklistPromise =\n this.#queryConfig<C2DomainBlocklistResponse>(C2_DOMAIN_BLOCKLIST_URL);\n\n [stalelistResponse, c2DomainBlocklistResponse] = await Promise.all([\n stalelistPromise,\n c2DomainBlocklistPromise,\n ]);\n // Fetching hotlist diffs relies on having a lastUpdated timestamp to do `GET /v1/diffsSince/:timestamp`,\n // so it doesn't make sense to call if there is not a timestamp to begin with.\n if (stalelistResponse?.data && stalelistResponse.data.lastUpdated > 0) {\n hotlistDiffsResponse = await this.#queryConfig<\n DataResultWrapper<Hotlist>\n >(`${METAMASK_HOTLIST_DIFF_URL}/${stalelistResponse.data.lastUpdated}`);\n }\n } finally {\n // Set `stalelistLastFetched` and `hotlistLastFetched` even for failed requests to prevent server\n // from being overwhelmed with traffic after a network disruption.\n const timeNow = fetchTimeNow();\n this.update((draftState) => {\n draftState.stalelistLastFetched = timeNow;\n draftState.hotlistLastFetched = timeNow;\n draftState.c2DomainBlocklistLastFetched = timeNow;\n });\n }\n\n if (!stalelistResponse || !hotlistDiffsResponse) {\n return;\n }\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const { eth_phishing_detect_config, ...partialState } =\n stalelistResponse.data;\n\n const metamaskListState: PhishingListState = {\n ...eth_phishing_detect_config,\n ...partialState,\n c2DomainBlocklist: c2DomainBlocklistResponse\n ? c2DomainBlocklistResponse.recentlyAdded\n : [],\n name: phishingListKeyNameMap.eth_phishing_detect_config,\n };\n\n const newMetaMaskListState: PhishingListState = applyDiffs(\n metamaskListState,\n hotlistDiffsResponse.data,\n ListKeys.EthPhishingDetectConfig,\n );\n\n this.update((draftState) => {\n draftState.phishingLists = [newMetaMaskListState];\n });\n this.updatePhishingDetector();\n }\n\n /**\n * Update the stalelist configuration.\n *\n * This should only be called from the `updateStalelist` function, which is a wrapper around\n * this function that prevents redundant configuration updates.\n */\n async #updateHotlist() {\n const lastDiffTimestamp = Math.max(\n ...this.state.phishingLists.map(({ lastUpdated }) => lastUpdated),\n );\n let hotlistResponse: DataResultWrapper<Hotlist> | null;\n\n try {\n hotlistResponse = await this.#queryConfig<DataResultWrapper<Hotlist>>(\n `${METAMASK_HOTLIST_DIFF_URL}/${lastDiffTimestamp}`,\n );\n } finally {\n // Set `hotlistLastFetched` even for failed requests to prevent server from being overwhelmed with\n // traffic after a network disruption.\n this.update((draftState) => {\n draftState.hotlistLastFetched = fetchTimeNow();\n });\n }\n\n if (!hotlistResponse?.data) {\n return;\n }\n const hotlist = hotlistResponse.data;\n const newPhishingLists = this.state.phishingLists.map((phishingList) => {\n const updatedList = applyDiffs(\n phishingList,\n hotlist,\n phishingListNameKeyMap[phishingList.name],\n [],\n [],\n );\n\n return updatedList;\n });\n\n this.update((draftState) => {\n draftState.phishingLists = newPhishingLists;\n });\n this.updatePhishingDetector();\n }\n\n /**\n * Update the C2 domain blocklist.\n *\n * This should only be called from the `updateC2DomainBlocklist` function, which is a wrapper around\n * this function that prevents redundant configuration updates.\n */\n async #updateC2DomainBlocklist() {\n let c2DomainBlocklistResponse: C2DomainBlocklistResponse | null = null;\n\n try {\n c2DomainBlocklistResponse =\n await this.#queryConfig<C2DomainBlocklistResponse>(\n `${C2_DOMAIN_BLOCKLIST_URL}?timestamp=${roundToNearestMinute(\n this.state.c2DomainBlocklistLastFetched,\n )}`,\n );\n } finally {\n // Set `c2DomainBlocklistLastFetched` even for failed requests to prevent server from being overwhelmed with\n // traffic after a network disruption.\n this.update((draftState) => {\n draftState.c2DomainBlocklistLastFetched = fetchTimeNow();\n });\n }\n\n if (!c2DomainBlocklistResponse) {\n return;\n }\n\n const recentlyAddedC2Domains = c2DomainBlocklistResponse.recentlyAdded;\n const recentlyRemovedC2Domains = c2DomainBlocklistResponse.recentlyRemoved;\n\n const newPhishingLists = this.state.phishingLists.map((phishingList) => {\n const updatedList = applyDiffs(\n phishingList,\n [],\n phishingListNameKeyMap[phishingList.name],\n recentlyAddedC2Domains,\n recentlyRemovedC2Domains,\n );\n\n return updatedList;\n });\n\n this.update((draftState) => {\n draftState.phishingLists = newPhishingLists;\n });\n this.updatePhishingDetector();\n }\n\n async #queryConfig<ResponseType>(\n input: RequestInfo,\n ): Promise<ResponseType | null> {\n const response = await safelyExecute(\n () => fetch(input, { cache: 'no-cache' }),\n true,\n );\n\n switch (response?.status) {\n case 200: {\n return await response.json();\n }\n\n default: {\n return null;\n }\n }\n }\n}\n\nexport default PhishingController;\n\nexport type { PhishingDetectorResult };\n"]}
|
|
1
|
+
{"version":3,"file":"PhishingController.mjs","sourceRoot":"","sources":["../src/PhishingController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedMessenger,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport {\n safelyExecute,\n safelyExecuteWithTimeout,\n} from '@metamask/controller-utils';\nimport { toASCII } from 'punycode/punycode.js';\n\nimport { PhishingDetector } from './PhishingDetector';\nimport {\n PhishingDetectorResultType,\n type PhishingDetectorResult,\n type PhishingDetectionScanResult,\n RecommendedAction,\n} from './types';\nimport {\n applyDiffs,\n fetchTimeNow,\n getHostnameFromUrl,\n roundToNearestMinute,\n getHostnameFromWebUrl,\n} from './utils';\n\nexport const PHISHING_CONFIG_BASE_URL =\n 'https://phishing-detection.api.cx.metamask.io';\nexport const METAMASK_STALELIST_FILE = '/v1/stalelist';\nexport const METAMASK_HOTLIST_DIFF_FILE = '/v1/diffsSince';\n\nexport const CLIENT_SIDE_DETECION_BASE_URL =\n 'https://client-side-detection.api.cx.metamask.io';\nexport const C2_DOMAIN_BLOCKLIST_ENDPOINT = '/v1/request-blocklist';\n\nexport const PHISHING_DETECTION_BASE_URL =\n 'https://dapp-scanning.api.cx.metamask.io';\nexport const PHISHING_DETECTION_SCAN_ENDPOINT = 'scan';\n\nexport const C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL = 5 * 60; // 5 mins in seconds\nexport const HOTLIST_REFRESH_INTERVAL = 5 * 60; // 5 mins in seconds\nexport const STALELIST_REFRESH_INTERVAL = 30 * 24 * 60 * 60; // 30 days in seconds\n\nexport const METAMASK_STALELIST_URL = `${PHISHING_CONFIG_BASE_URL}${METAMASK_STALELIST_FILE}`;\nexport const METAMASK_HOTLIST_DIFF_URL = `${PHISHING_CONFIG_BASE_URL}${METAMASK_HOTLIST_DIFF_FILE}`;\nexport const C2_DOMAIN_BLOCKLIST_URL = `${CLIENT_SIDE_DETECION_BASE_URL}${C2_DOMAIN_BLOCKLIST_ENDPOINT}`;\n\n/**\n * @type ListTypes\n *\n * Type outlining the types of lists provided by aggregating different source lists\n */\nexport type ListTypes =\n | 'fuzzylist'\n | 'blocklist'\n | 'allowlist'\n | 'c2DomainBlocklist';\n\n/**\n * @type EthPhishingResponse\n *\n * Configuration response from the eth-phishing-detect package\n * consisting of approved and unapproved website origins\n * @property blacklist - List of unapproved origins\n * @property fuzzylist - List of fuzzy-matched unapproved origins\n * @property tolerance - Fuzzy match tolerance level\n * @property version - Version number of this configuration\n * @property whitelist - List of approved origins\n */\nexport type EthPhishingResponse = {\n blacklist: string[];\n fuzzylist: string[];\n tolerance: number;\n version: number;\n whitelist: string[];\n};\n\n/**\n * @type C2DomainBlocklistResponse\n *\n * Response for blocklist update requests\n * @property recentlyAdded - List of c2 domains recently added to the blocklist\n * @property recentlyRemoved - List of c2 domains recently removed from the blocklist\n * @property lastFetchedAt - Timestamp of the last fetch request\n */\nexport type C2DomainBlocklistResponse = {\n recentlyAdded: string[];\n recentlyRemoved: string[];\n lastFetchedAt: string;\n};\n\n/**\n * @type PhishingStalelist\n *\n * type defining expected type of the stalelist.json file.\n * @property eth_phishing_detect_config - Stale list sourced from eth-phishing-detect's config.json.\n * @property tolerance - Fuzzy match tolerance level\n * @property lastUpdated - Timestamp of last update.\n * @property version - Stalelist data structure iteration.\n */\nexport type PhishingStalelist = {\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n eth_phishing_detect_config: Record<ListTypes, string[]>;\n tolerance: number;\n version: number;\n lastUpdated: number;\n};\n\n/**\n * @type PhishingListState\n *\n * type defining the persisted list state. This is the persisted state that is updated frequently with `this.maybeUpdateState()`.\n * @property allowlist - List of approved origins (legacy naming \"whitelist\")\n * @property blocklist - List of unapproved origins (legacy naming \"blacklist\")\n * @property c2DomainBlocklist - List of hashed hostnames that C2 requests are blocked against.\n * @property fuzzylist - List of fuzzy-matched unapproved origins\n * @property tolerance - Fuzzy match tolerance level\n * @property lastUpdated - Timestamp of last update.\n * @property version - Version of the phishing list state.\n * @property name - Name of the list. Used for attribution.\n */\nexport type PhishingListState = {\n allowlist: string[];\n blocklist: string[];\n c2DomainBlocklist: string[];\n fuzzylist: string[];\n tolerance: number;\n version: number;\n lastUpdated: number;\n name: ListNames;\n};\n\n/**\n * @type HotlistDiff\n *\n * type defining the expected type of the diffs in hotlist.json file.\n * @property url - Url of the diff entry.\n * @property timestamp - Timestamp at which the diff was identified.\n * @property targetList - The list name where the diff was identified.\n * @property isRemoval - Was the diff identified a removal type.\n */\nexport type HotlistDiff = {\n url: string;\n timestamp: number;\n targetList: `${ListKeys}.${ListTypes}`;\n isRemoval?: boolean;\n};\n\n// TODO: Either fix this lint violation or explain why it's necessary to ignore.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport type DataResultWrapper<T> = {\n data: T;\n};\n\n/**\n * @type Hotlist\n *\n * Type defining expected hotlist.json file.\n * @property url - Url of the diff entry.\n * @property timestamp - Timestamp at which the diff was identified.\n * @property targetList - The list name where the diff was identified.\n * @property isRemoval - Was the diff identified a removal type.\n */\nexport type Hotlist = HotlistDiff[];\n\n/**\n * Enum containing upstream data provider source list keys.\n * These are the keys denoting lists consumed by the upstream data provider.\n */\nexport enum ListKeys {\n EthPhishingDetectConfig = 'eth_phishing_detect_config',\n}\n\n/**\n * Enum containing downstream client attribution names.\n */\nexport enum ListNames {\n MetaMask = 'MetaMask',\n}\n\n/**\n * Maps from downstream client attribution name\n * to list key sourced from upstream data provider.\n */\nconst phishingListNameKeyMap = {\n [ListNames.MetaMask]: ListKeys.EthPhishingDetectConfig,\n};\n\n/**\n * Maps from list key sourced from upstream data\n * provider to downstream client attribution name.\n */\nexport const phishingListKeyNameMap = {\n [ListKeys.EthPhishingDetectConfig]: ListNames.MetaMask,\n};\n\nconst controllerName = 'PhishingController';\n\nconst metadata = {\n phishingLists: { persist: true, anonymous: false },\n whitelist: { persist: true, anonymous: false },\n hotlistLastFetched: { persist: true, anonymous: false },\n stalelistLastFetched: { persist: true, anonymous: false },\n c2DomainBlocklistLastFetched: { persist: true, anonymous: false },\n};\n\n/**\n * Get a default empty state for the controller.\n * @returns The default empty state.\n */\nconst getDefaultState = (): PhishingControllerState => {\n return {\n phishingLists: [],\n whitelist: [],\n hotlistLastFetched: 0,\n stalelistLastFetched: 0,\n c2DomainBlocklistLastFetched: 0,\n };\n};\n\n/**\n * @type PhishingControllerState\n *\n * Phishing controller state\n * @property phishing - eth-phishing-detect configuration\n * @property whitelist - array of temporarily-approved origins\n */\nexport type PhishingControllerState = {\n phishingLists: PhishingListState[];\n whitelist: string[];\n hotlistLastFetched: number;\n stalelistLastFetched: number;\n c2DomainBlocklistLastFetched: number;\n};\n\n/**\n * @type PhishingControllerOptions\n *\n * Phishing controller options\n * @property stalelistRefreshInterval - Polling interval used to fetch stale list.\n * @property hotlistRefreshInterval - Polling interval used to fetch hotlist diff list.\n * @property c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.\n */\nexport type PhishingControllerOptions = {\n stalelistRefreshInterval?: number;\n hotlistRefreshInterval?: number;\n c2DomainBlocklistRefreshInterval?: number;\n messenger: PhishingControllerMessenger;\n state?: Partial<PhishingControllerState>;\n};\n\nexport type MaybeUpdateState = {\n type: `${typeof controllerName}:maybeUpdateState`;\n handler: PhishingController['maybeUpdateState'];\n};\n\nexport type TestOrigin = {\n type: `${typeof controllerName}:testOrigin`;\n handler: PhishingController['test'];\n};\n\nexport type PhishingControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n PhishingControllerState\n>;\n\nexport type PhishingControllerActions =\n | PhishingControllerGetStateAction\n | MaybeUpdateState\n | TestOrigin;\n\nexport type PhishingControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n PhishingControllerState\n>;\n\nexport type PhishingControllerEvents = PhishingControllerStateChangeEvent;\n\nexport type PhishingControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n PhishingControllerActions,\n PhishingControllerEvents,\n never,\n never\n>;\n\n/**\n * Controller that manages community-maintained lists of approved and unapproved website origins.\n */\nexport class PhishingController extends BaseController<\n typeof controllerName,\n PhishingControllerState,\n PhishingControllerMessenger\n> {\n // TODO: Replace `any` with type\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n #detector: any;\n\n #stalelistRefreshInterval: number;\n\n #hotlistRefreshInterval: number;\n\n #c2DomainBlocklistRefreshInterval: number;\n\n #inProgressHotlistUpdate?: Promise<void>;\n\n #inProgressStalelistUpdate?: Promise<void>;\n\n #isProgressC2DomainBlocklistUpdate?: Promise<void>;\n\n /**\n * Construct a Phishing Controller.\n *\n * @param config - Initial options used to configure this controller.\n * @param config.stalelistRefreshInterval - Polling interval used to fetch stale list.\n * @param config.hotlistRefreshInterval - Polling interval used to fetch hotlist diff list.\n * @param config.c2DomainBlocklistRefreshInterval - Polling interval used to fetch c2 domain blocklist.\n * @param config.messenger - The controller restricted messenger.\n * @param config.state - Initial state to set on this controller.\n */\n constructor({\n stalelistRefreshInterval = STALELIST_REFRESH_INTERVAL,\n hotlistRefreshInterval = HOTLIST_REFRESH_INTERVAL,\n c2DomainBlocklistRefreshInterval = C2_DOMAIN_BLOCKLIST_REFRESH_INTERVAL,\n messenger,\n state = {},\n }: PhishingControllerOptions) {\n super({\n name: controllerName,\n metadata,\n messenger,\n state: {\n ...getDefaultState(),\n ...state,\n },\n });\n\n this.#stalelistRefreshInterval = stalelistRefreshInterval;\n this.#hotlistRefreshInterval = hotlistRefreshInterval;\n this.#c2DomainBlocklistRefreshInterval = c2DomainBlocklistRefreshInterval;\n this.#registerMessageHandlers();\n\n this.updatePhishingDetector();\n }\n\n /**\n * Constructor helper for registering this controller's messaging system\n * actions.\n */\n #registerMessageHandlers(): void {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:maybeUpdateState` as const,\n this.maybeUpdateState.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:testOrigin` as const,\n this.test.bind(this),\n );\n }\n\n /**\n * Updates this.detector with an instance of PhishingDetector using the current state.\n */\n updatePhishingDetector() {\n this.#detector = new PhishingDetector(this.state.phishingLists);\n }\n\n /**\n * Set the interval at which the stale phishing list will be refetched.\n * Fetching will only occur on the next call to test/bypass.\n * For immediate update to the phishing list, call {@link updateStalelist} directly.\n *\n * @param interval - the new interval, in ms.\n */\n setStalelistRefreshInterval(interval: number) {\n this.#stalelistRefreshInterval = interval;\n }\n\n /**\n * Set the interval at which the hot list will be refetched.\n * Fetching will only occur on the next call to test/bypass.\n * For immediate update to the phishing list, call {@link updateHotlist} directly.\n *\n * @param interval - the new interval, in ms.\n */\n setHotlistRefreshInterval(interval: number) {\n this.#hotlistRefreshInterval = interval;\n }\n\n /**\n * Set the interval at which the C2 domain blocklist will be refetched.\n * Fetching will only occur on the next call to test/bypass.\n * For immediate update to the phishing list, call {@link updateHotlist} directly.\n *\n * @param interval - the new interval, in ms.\n */\n setC2DomainBlocklistRefreshInterval(interval: number) {\n this.#c2DomainBlocklistRefreshInterval = interval;\n }\n\n /**\n * Determine if an update to the stalelist configuration is needed.\n *\n * @returns Whether an update is needed\n */\n isStalelistOutOfDate() {\n return (\n fetchTimeNow() - this.state.stalelistLastFetched >=\n this.#stalelistRefreshInterval\n );\n }\n\n /**\n * Determine if an update to the hotlist configuration is needed.\n *\n * @returns Whether an update is needed\n */\n isHotlistOutOfDate() {\n return (\n fetchTimeNow() - this.state.hotlistLastFetched >=\n this.#hotlistRefreshInterval\n );\n }\n\n /**\n * Determine if an update to the C2 domain blocklist is needed.\n *\n * @returns Whether an update is needed\n */\n isC2DomainBlocklistOutOfDate() {\n return (\n fetchTimeNow() - this.state.c2DomainBlocklistLastFetched >=\n this.#c2DomainBlocklistRefreshInterval\n );\n }\n\n /**\n * Conditionally update the phishing configuration.\n *\n * If the stalelist configuration is out of date, this function will call `updateStalelist`\n * to update the configuration. This will automatically grab the hotlist,\n * so it isn't necessary to continue on to download the hotlist and the c2 domain blocklist.\n *\n */\n async maybeUpdateState() {\n const staleListOutOfDate = this.isStalelistOutOfDate();\n if (staleListOutOfDate) {\n await this.updateStalelist();\n return;\n }\n const hotlistOutOfDate = this.isHotlistOutOfDate();\n if (hotlistOutOfDate) {\n await this.updateHotlist();\n }\n const c2DomainBlocklistOutOfDate = this.isC2DomainBlocklistOutOfDate();\n if (c2DomainBlocklistOutOfDate) {\n await this.updateC2DomainBlocklist();\n }\n }\n\n /**\n * Determines if a given origin is unapproved.\n *\n * It is strongly recommended that you call {@link maybeUpdateState} before calling this,\n * to check whether the phishing configuration is up-to-date. It will be updated if necessary\n * by calling {@link updateStalelist} or {@link updateHotlist}.\n *\n * @param origin - Domain origin of a website.\n * @returns Whether the origin is an unapproved origin.\n */\n test(origin: string): PhishingDetectorResult {\n const punycodeOrigin = toASCII(origin);\n const hostname = getHostnameFromUrl(punycodeOrigin);\n if (this.state.whitelist.includes(hostname || punycodeOrigin)) {\n return { result: false, type: PhishingDetectorResultType.All }; // Same as whitelisted match returned by detector.check(...).\n }\n return this.#detector.check(punycodeOrigin);\n }\n\n /**\n * Checks if a request URL's domain is blocked against the request blocklist.\n *\n * This method is used to determine if a specific request URL is associated with a malicious\n * command and control (C2) domain. The URL's hostname is hashed and checked against a configured\n * blocklist of known malicious domains.\n *\n * @param origin - The full request URL to be checked.\n * @returns An object indicating whether the URL's domain is blocked and relevant metadata.\n */\n isBlockedRequest(origin: string): PhishingDetectorResult {\n const punycodeOrigin = toASCII(origin);\n const hostname = getHostnameFromUrl(punycodeOrigin);\n if (this.state.whitelist.includes(hostname || punycodeOrigin)) {\n return { result: false, type: PhishingDetectorResultType.All }; // Same as whitelisted match returned by detector.check(...).\n }\n return this.#detector.isMaliciousC2Domain(punycodeOrigin);\n }\n\n /**\n * Temporarily marks a given origin as approved.\n *\n * @param origin - The origin to mark as approved.\n */\n bypass(origin: string) {\n const punycodeOrigin = toASCII(origin);\n const hostname = getHostnameFromUrl(punycodeOrigin);\n const { whitelist } = this.state;\n if (whitelist.includes(hostname || punycodeOrigin)) {\n return;\n }\n this.update((draftState) => {\n draftState.whitelist.push(hostname || punycodeOrigin);\n });\n }\n\n /**\n * Update the C2 domain blocklist.\n *\n * If an update is in progress, no additional update will be made. Instead this will wait until\n * the in-progress update has finished.\n */\n async updateC2DomainBlocklist() {\n if (this.#isProgressC2DomainBlocklistUpdate) {\n await this.#isProgressC2DomainBlocklistUpdate;\n return;\n }\n\n try {\n this.#isProgressC2DomainBlocklistUpdate = this.#updateC2DomainBlocklist();\n await this.#isProgressC2DomainBlocklistUpdate;\n } finally {\n this.#isProgressC2DomainBlocklistUpdate = undefined;\n }\n }\n\n /**\n * Update the hotlist.\n *\n * If an update is in progress, no additional update will be made. Instead this will wait until\n * the in-progress update has finished.\n */\n async updateHotlist() {\n if (this.#inProgressHotlistUpdate) {\n await this.#inProgressHotlistUpdate;\n return;\n }\n\n try {\n this.#inProgressHotlistUpdate = this.#updateHotlist();\n await this.#inProgressHotlistUpdate;\n } finally {\n this.#inProgressHotlistUpdate = undefined;\n }\n }\n\n /**\n * Update the stalelist.\n *\n * If an update is in progress, no additional update will be made. Instead this will wait until\n * the in-progress update has finished.\n */\n async updateStalelist() {\n if (this.#inProgressStalelistUpdate) {\n await this.#inProgressStalelistUpdate;\n return;\n }\n\n try {\n this.#inProgressStalelistUpdate = this.#updateStalelist();\n await this.#inProgressStalelistUpdate;\n } finally {\n this.#inProgressStalelistUpdate = undefined;\n }\n }\n\n /**\n * Scan a URL for phishing. It will only scan the hostname of the URL. It also only supports\n * web URLs.\n *\n * @param url - The URL to scan.\n * @returns The phishing detection scan result.\n */\n scanUrl = async (url: string): Promise<PhishingDetectionScanResult> => {\n const [hostname, ok] = getHostnameFromWebUrl(url);\n if (!ok) {\n return {\n domainName: '',\n recommendedAction: RecommendedAction.None,\n fetchError: 'url is not a valid web URL',\n };\n }\n\n const apiResponse = await safelyExecuteWithTimeout(\n async () => {\n const res = await fetch(\n `${PHISHING_DETECTION_BASE_URL}/${PHISHING_DETECTION_SCAN_ENDPOINT}?url=${encodeURIComponent(hostname)}`,\n {\n method: 'GET',\n headers: {\n Accept: 'application/json',\n },\n },\n );\n if (!res.ok) {\n return {\n error: `${res.status} ${res.statusText}`,\n };\n }\n const data = await res.json();\n return data;\n },\n true,\n 8000,\n );\n\n // Need to do it this way because safelyExecuteWithTimeout returns undefined for both timeouts and errors.\n if (!apiResponse) {\n return {\n domainName: '',\n recommendedAction: RecommendedAction.None,\n fetchError: 'timeout of 8000ms exceeded',\n };\n } else if ('error' in apiResponse) {\n return {\n domainName: '',\n recommendedAction: RecommendedAction.None,\n fetchError: apiResponse.error,\n };\n }\n\n return {\n domainName: hostname,\n recommendedAction: apiResponse.recommendedAction,\n } as PhishingDetectionScanResult;\n };\n\n /**\n * Update the stalelist configuration.\n *\n * This should only be called from the `updateStalelist` function, which is a wrapper around\n * this function that prevents redundant configuration updates.\n */\n async #updateStalelist() {\n let stalelistResponse: DataResultWrapper<PhishingStalelist> | null = null;\n let hotlistDiffsResponse: DataResultWrapper<Hotlist> | null = null;\n let c2DomainBlocklistResponse: C2DomainBlocklistResponse | null = null;\n try {\n const stalelistPromise = this.#queryConfig<\n DataResultWrapper<PhishingStalelist>\n >(METAMASK_STALELIST_URL);\n\n const c2DomainBlocklistPromise =\n this.#queryConfig<C2DomainBlocklistResponse>(C2_DOMAIN_BLOCKLIST_URL);\n\n [stalelistResponse, c2DomainBlocklistResponse] = await Promise.all([\n stalelistPromise,\n c2DomainBlocklistPromise,\n ]);\n // Fetching hotlist diffs relies on having a lastUpdated timestamp to do `GET /v1/diffsSince/:timestamp`,\n // so it doesn't make sense to call if there is not a timestamp to begin with.\n if (stalelistResponse?.data && stalelistResponse.data.lastUpdated > 0) {\n hotlistDiffsResponse = await this.#queryConfig<\n DataResultWrapper<Hotlist>\n >(`${METAMASK_HOTLIST_DIFF_URL}/${stalelistResponse.data.lastUpdated}`);\n }\n } finally {\n // Set `stalelistLastFetched` and `hotlistLastFetched` even for failed requests to prevent server\n // from being overwhelmed with traffic after a network disruption.\n const timeNow = fetchTimeNow();\n this.update((draftState) => {\n draftState.stalelistLastFetched = timeNow;\n draftState.hotlistLastFetched = timeNow;\n draftState.c2DomainBlocklistLastFetched = timeNow;\n });\n }\n\n if (!stalelistResponse || !hotlistDiffsResponse) {\n return;\n }\n\n // TODO: Either fix this lint violation or explain why it's necessary to ignore.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const { eth_phishing_detect_config, ...partialState } =\n stalelistResponse.data;\n\n const metamaskListState: PhishingListState = {\n ...eth_phishing_detect_config,\n ...partialState,\n c2DomainBlocklist: c2DomainBlocklistResponse\n ? c2DomainBlocklistResponse.recentlyAdded\n : [],\n name: phishingListKeyNameMap.eth_phishing_detect_config,\n };\n\n const newMetaMaskListState: PhishingListState = applyDiffs(\n metamaskListState,\n hotlistDiffsResponse.data,\n ListKeys.EthPhishingDetectConfig,\n );\n\n this.update((draftState) => {\n draftState.phishingLists = [newMetaMaskListState];\n });\n this.updatePhishingDetector();\n }\n\n /**\n * Update the stalelist configuration.\n *\n * This should only be called from the `updateStalelist` function, which is a wrapper around\n * this function that prevents redundant configuration updates.\n */\n async #updateHotlist() {\n const lastDiffTimestamp = Math.max(\n ...this.state.phishingLists.map(({ lastUpdated }) => lastUpdated),\n );\n let hotlistResponse: DataResultWrapper<Hotlist> | null;\n\n try {\n hotlistResponse = await this.#queryConfig<DataResultWrapper<Hotlist>>(\n `${METAMASK_HOTLIST_DIFF_URL}/${lastDiffTimestamp}`,\n );\n } finally {\n // Set `hotlistLastFetched` even for failed requests to prevent server from being overwhelmed with\n // traffic after a network disruption.\n this.update((draftState) => {\n draftState.hotlistLastFetched = fetchTimeNow();\n });\n }\n\n if (!hotlistResponse?.data) {\n return;\n }\n const hotlist = hotlistResponse.data;\n const newPhishingLists = this.state.phishingLists.map((phishingList) => {\n const updatedList = applyDiffs(\n phishingList,\n hotlist,\n phishingListNameKeyMap[phishingList.name],\n [],\n [],\n );\n\n return updatedList;\n });\n\n this.update((draftState) => {\n draftState.phishingLists = newPhishingLists;\n });\n this.updatePhishingDetector();\n }\n\n /**\n * Update the C2 domain blocklist.\n *\n * This should only be called from the `updateC2DomainBlocklist` function, which is a wrapper around\n * this function that prevents redundant configuration updates.\n */\n async #updateC2DomainBlocklist() {\n let c2DomainBlocklistResponse: C2DomainBlocklistResponse | null = null;\n\n try {\n c2DomainBlocklistResponse =\n await this.#queryConfig<C2DomainBlocklistResponse>(\n `${C2_DOMAIN_BLOCKLIST_URL}?timestamp=${roundToNearestMinute(\n this.state.c2DomainBlocklistLastFetched,\n )}`,\n );\n } finally {\n // Set `c2DomainBlocklistLastFetched` even for failed requests to prevent server from being overwhelmed with\n // traffic after a network disruption.\n this.update((draftState) => {\n draftState.c2DomainBlocklistLastFetched = fetchTimeNow();\n });\n }\n\n if (!c2DomainBlocklistResponse) {\n return;\n }\n\n const recentlyAddedC2Domains = c2DomainBlocklistResponse.recentlyAdded;\n const recentlyRemovedC2Domains = c2DomainBlocklistResponse.recentlyRemoved;\n\n const newPhishingLists = this.state.phishingLists.map((phishingList) => {\n const updatedList = applyDiffs(\n phishingList,\n [],\n phishingListNameKeyMap[phishingList.name],\n recentlyAddedC2Domains,\n recentlyRemovedC2Domains,\n );\n\n return updatedList;\n });\n\n this.update((draftState) => {\n draftState.phishingLists = newPhishingLists;\n });\n this.updatePhishingDetector();\n }\n\n async #queryConfig<ResponseType>(\n input: RequestInfo,\n ): Promise<ResponseType | null> {\n const response = await safelyExecute(\n () => fetch(input, { cache: 'no-cache' }),\n true,\n );\n\n switch (response?.status) {\n case 200: {\n return await response.json();\n }\n\n default: {\n return null;\n }\n }\n }\n}\n\nexport default PhishingController;\n\nexport type { PhishingDetectorResult };\n"]}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2DAAqC;AAQrC,2DAAsD;AAA7C,oHAAA,gBAAgB,OAAA;
|
|
1
|
+
{"version":3,"file":"index.cjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2DAAqC;AAQrC,2DAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AAEzB,qCAAqD;AAA5C,mHAAA,0BAA0B,OAAA","sourcesContent":["export * from './PhishingController';\nexport type {\n LegacyPhishingDetectorList,\n PhishingDetectorList,\n FuzzyTolerance,\n PhishingDetectorOptions,\n PhishingDetectorConfiguration,\n} from './PhishingDetector';\nexport { PhishingDetector } from './PhishingDetector';\nexport type { PhishingDetectionScanResult } from './types';\nexport { PhishingDetectorResultType } from './types';\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from "./PhishingController.cjs";
|
|
2
2
|
export type { LegacyPhishingDetectorList, PhishingDetectorList, FuzzyTolerance, PhishingDetectorOptions, PhishingDetectorConfiguration, } from "./PhishingDetector.cjs";
|
|
3
3
|
export { PhishingDetector } from "./PhishingDetector.cjs";
|
|
4
|
+
export type { PhishingDetectionScanResult } from "./types.cjs";
|
|
4
5
|
export { PhishingDetectorResultType } from "./types.cjs";
|
|
5
6
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAqC;AACrC,YAAY,EACV,0BAA0B,EAC1B,oBAAoB,EACpB,cAAc,EACd,uBAAuB,EACvB,6BAA6B,GAC9B,+BAA2B;AAC5B,OAAO,EAAE,gBAAgB,EAAE,+BAA2B;AACtD,OAAO,EAAE,0BAA0B,EAAE,oBAAgB"}
|
|
1
|
+
{"version":3,"file":"index.d.cts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAqC;AACrC,YAAY,EACV,0BAA0B,EAC1B,oBAAoB,EACpB,cAAc,EACd,uBAAuB,EACvB,6BAA6B,GAC9B,+BAA2B;AAC5B,OAAO,EAAE,gBAAgB,EAAE,+BAA2B;AACtD,YAAY,EAAE,2BAA2B,EAAE,oBAAgB;AAC3D,OAAO,EAAE,0BAA0B,EAAE,oBAAgB"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from "./PhishingController.mjs";
|
|
2
2
|
export type { LegacyPhishingDetectorList, PhishingDetectorList, FuzzyTolerance, PhishingDetectorOptions, PhishingDetectorConfiguration, } from "./PhishingDetector.mjs";
|
|
3
3
|
export { PhishingDetector } from "./PhishingDetector.mjs";
|
|
4
|
+
export type { PhishingDetectionScanResult } from "./types.mjs";
|
|
4
5
|
export { PhishingDetectorResultType } from "./types.mjs";
|
|
5
6
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAqC;AACrC,YAAY,EACV,0BAA0B,EAC1B,oBAAoB,EACpB,cAAc,EACd,uBAAuB,EACvB,6BAA6B,GAC9B,+BAA2B;AAC5B,OAAO,EAAE,gBAAgB,EAAE,+BAA2B;AACtD,OAAO,EAAE,0BAA0B,EAAE,oBAAgB"}
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAqC;AACrC,YAAY,EACV,0BAA0B,EAC1B,oBAAoB,EACpB,cAAc,EACd,uBAAuB,EACvB,6BAA6B,GAC9B,+BAA2B;AAC5B,OAAO,EAAE,gBAAgB,EAAE,+BAA2B;AACtD,YAAY,EAAE,2BAA2B,EAAE,oBAAgB;AAC3D,OAAO,EAAE,0BAA0B,EAAE,oBAAgB"}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAqC;AAQrC,OAAO,EAAE,gBAAgB,EAAE,+BAA2B;
|
|
1
|
+
{"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,yCAAqC;AAQrC,OAAO,EAAE,gBAAgB,EAAE,+BAA2B;AAEtD,OAAO,EAAE,0BAA0B,EAAE,oBAAgB","sourcesContent":["export * from './PhishingController';\nexport type {\n LegacyPhishingDetectorList,\n PhishingDetectorList,\n FuzzyTolerance,\n PhishingDetectorOptions,\n PhishingDetectorConfiguration,\n} from './PhishingDetector';\nexport { PhishingDetector } from './PhishingDetector';\nexport type { PhishingDetectionScanResult } from './types';\nexport { PhishingDetectorResultType } from './types';\n"]}
|
package/dist/types.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PhishingDetectorResultType = void 0;
|
|
3
|
+
exports.RecommendedAction = exports.PhishingDetectorResultType = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* The type of list in which the domain was found.
|
|
6
6
|
*/
|
|
@@ -37,4 +37,22 @@ var PhishingDetectorResultType;
|
|
|
37
37
|
*/
|
|
38
38
|
PhishingDetectorResultType["C2DomainBlocklist"] = "c2DomainBlocklist";
|
|
39
39
|
})(PhishingDetectorResultType || (exports.PhishingDetectorResultType = PhishingDetectorResultType = {}));
|
|
40
|
+
/**
|
|
41
|
+
* Indicates the warning level based on risk factors
|
|
42
|
+
*/
|
|
43
|
+
var RecommendedAction;
|
|
44
|
+
(function (RecommendedAction) {
|
|
45
|
+
/**
|
|
46
|
+
* None means it is most likely safe
|
|
47
|
+
*/
|
|
48
|
+
RecommendedAction["None"] = "NONE";
|
|
49
|
+
/**
|
|
50
|
+
* Warn means there is some risk
|
|
51
|
+
*/
|
|
52
|
+
RecommendedAction["Warn"] = "WARN";
|
|
53
|
+
/**
|
|
54
|
+
* Block means it is highly likely to be malicious
|
|
55
|
+
*/
|
|
56
|
+
RecommendedAction["Block"] = "BLOCK";
|
|
57
|
+
})(RecommendedAction || (exports.RecommendedAction = RecommendedAction = {}));
|
|
40
58
|
//# sourceMappingURL=types.cjs.map
|
package/dist/types.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.cjs","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAsCA;;GAEG;AACH,IAAY,0BA+BX;AA/BD,WAAY,0BAA0B;IACpC;;OAEG;IACH,yCAAW,CAAA;IACX;;OAEG;IACH,6CAAe,CAAA;IACf;;OAEG;IACH,qDAAuB,CAAA;IACvB;;OAEG;IACH,qDAAuB,CAAA;IACvB;;;OAGG;IACH,qDAAuB,CAAA;IACvB;;;OAGG;IACH,qDAAuB,CAAA;IACvB;;OAEG;IACH,qEAAuC,CAAA;AACzC,CAAC,EA/BW,0BAA0B,0CAA1B,0BAA0B,QA+BrC","sourcesContent":["/**\n * Represents the result of checking a domain.\n */\nexport type PhishingDetectorResult = {\n /**\n * The name of the configuration object in which the domain was found within\n * an allowlist, blocklist, or fuzzylist.\n */\n name?: string;\n /**\n * The version associated with the configuration object in which the domain\n * was found within an allowlist, blocklist, or fuzzylist.\n */\n version?: string;\n /**\n * Whether the domain is regarded as allowed (true) or not (false).\n */\n result: boolean;\n /**\n * A normalized version of the domain, which is only constructed if the domain\n * is found within a list.\n */\n match?: string;\n /**\n * Which type of list in which the domain was found.\n *\n * - \"allowlist\" means that the domain was found in the allowlist.\n * - \"blocklist\" means that the domain was found in the blocklist.\n * - \"fuzzy\" means that the domain was found in the fuzzylist.\n * - \"blacklist\" means that the domain was found in a blacklist of a legacy\n * configuration object.\n * - \"whitelist\" means that the domain was found in a whitelist of a legacy\n * configuration object.\n * - \"all\" means that the domain was not found in any list.\n */\n type: PhishingDetectorResultType;\n};\n\n/**\n * The type of list in which the domain was found.\n */\nexport enum PhishingDetectorResultType {\n /*\n * \"all\" means that the domain was not found in any list.\n */\n All = 'all',\n /*\n * \"fuzzy\" means that the domain was found in the fuzzylist.\n */\n Fuzzy = 'fuzzy',\n /*\n * \"blocklist\" means that the domain was found in the blocklist.\n */\n Blocklist = 'blocklist',\n /*\n * \"allowlist\" means that the domain was found in the allowlist.\n */\n Allowlist = 'allowlist',\n /*\n * \"blacklist\" means that the domain was found in a blacklist of a legacy\n * configuration object.\n */\n Blacklist = 'blacklist',\n /*\n * \"whitelist\" means that the domain was found in a whitelist of a legacy\n * configuration object.\n */\n Whitelist = 'whitelist',\n /*\n * \"c2DomainBlocklist\" means that the domain was found in the C2 domain blocklist.\n */\n C2DomainBlocklist = 'c2DomainBlocklist',\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.cjs","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";;;AAsCA;;GAEG;AACH,IAAY,0BA+BX;AA/BD,WAAY,0BAA0B;IACpC;;OAEG;IACH,yCAAW,CAAA;IACX;;OAEG;IACH,6CAAe,CAAA;IACf;;OAEG;IACH,qDAAuB,CAAA;IACvB;;OAEG;IACH,qDAAuB,CAAA;IACvB;;;OAGG;IACH,qDAAuB,CAAA;IACvB;;;OAGG;IACH,qDAAuB,CAAA;IACvB;;OAEG;IACH,qEAAuC,CAAA;AACzC,CAAC,EA/BW,0BAA0B,0CAA1B,0BAA0B,QA+BrC;AA4BD;;GAEG;AACH,IAAY,iBAaX;AAbD,WAAY,iBAAiB;IAC3B;;OAEG;IACH,kCAAa,CAAA;IACb;;OAEG;IACH,kCAAa,CAAA;IACb;;OAEG;IACH,oCAAe,CAAA;AACjB,CAAC,EAbW,iBAAiB,iCAAjB,iBAAiB,QAa5B","sourcesContent":["/**\n * Represents the result of checking a domain.\n */\nexport type PhishingDetectorResult = {\n /**\n * The name of the configuration object in which the domain was found within\n * an allowlist, blocklist, or fuzzylist.\n */\n name?: string;\n /**\n * The version associated with the configuration object in which the domain\n * was found within an allowlist, blocklist, or fuzzylist.\n */\n version?: string;\n /**\n * Whether the domain is regarded as allowed (true) or not (false).\n */\n result: boolean;\n /**\n * A normalized version of the domain, which is only constructed if the domain\n * is found within a list.\n */\n match?: string;\n /**\n * Which type of list in which the domain was found.\n *\n * - \"allowlist\" means that the domain was found in the allowlist.\n * - \"blocklist\" means that the domain was found in the blocklist.\n * - \"fuzzy\" means that the domain was found in the fuzzylist.\n * - \"blacklist\" means that the domain was found in a blacklist of a legacy\n * configuration object.\n * - \"whitelist\" means that the domain was found in a whitelist of a legacy\n * configuration object.\n * - \"all\" means that the domain was not found in any list.\n */\n type: PhishingDetectorResultType;\n};\n\n/**\n * The type of list in which the domain was found.\n */\nexport enum PhishingDetectorResultType {\n /*\n * \"all\" means that the domain was not found in any list.\n */\n All = 'all',\n /*\n * \"fuzzy\" means that the domain was found in the fuzzylist.\n */\n Fuzzy = 'fuzzy',\n /*\n * \"blocklist\" means that the domain was found in the blocklist.\n */\n Blocklist = 'blocklist',\n /*\n * \"allowlist\" means that the domain was found in the allowlist.\n */\n Allowlist = 'allowlist',\n /*\n * \"blacklist\" means that the domain was found in a blacklist of a legacy\n * configuration object.\n */\n Blacklist = 'blacklist',\n /*\n * \"whitelist\" means that the domain was found in a whitelist of a legacy\n * configuration object.\n */\n Whitelist = 'whitelist',\n /*\n * \"c2DomainBlocklist\" means that the domain was found in the C2 domain blocklist.\n */\n C2DomainBlocklist = 'c2DomainBlocklist',\n}\n\n/**\n * PhishingDetectionScanResult represents the result of a phishing detection scan.\n */\nexport type PhishingDetectionScanResult = {\n /**\n * The domain name that was scanned.\n */\n domainName: string;\n /**\n * Indicates the warning level based on risk factors.\n *\n * - \"NONE\" means it is most likely safe.\n * - \"WARN\" means there is some risk.\n * - \"BLOCK\" means it is highly likely to be malicious.\n */\n recommendedAction: RecommendedAction;\n /**\n * An optional error message that exists if:\n * - The link requested is not a valid web URL.\n * - Failed to fetch the result from the phishing detector.\n *\n * Consumers can use the existence of this field to retry.\n */\n fetchError?: string;\n};\n\n/**\n * Indicates the warning level based on risk factors\n */\nexport enum RecommendedAction {\n /**\n * None means it is most likely safe\n */\n None = 'NONE',\n /**\n * Warn means there is some risk\n */\n Warn = 'WARN',\n /**\n * Block means it is highly likely to be malicious\n */\n Block = 'BLOCK',\n}\n"]}
|
package/dist/types.d.cts
CHANGED
|
@@ -47,4 +47,46 @@ export declare enum PhishingDetectorResultType {
|
|
|
47
47
|
Whitelist = "whitelist",
|
|
48
48
|
C2DomainBlocklist = "c2DomainBlocklist"
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* PhishingDetectionScanResult represents the result of a phishing detection scan.
|
|
52
|
+
*/
|
|
53
|
+
export type PhishingDetectionScanResult = {
|
|
54
|
+
/**
|
|
55
|
+
* The domain name that was scanned.
|
|
56
|
+
*/
|
|
57
|
+
domainName: string;
|
|
58
|
+
/**
|
|
59
|
+
* Indicates the warning level based on risk factors.
|
|
60
|
+
*
|
|
61
|
+
* - "NONE" means it is most likely safe.
|
|
62
|
+
* - "WARN" means there is some risk.
|
|
63
|
+
* - "BLOCK" means it is highly likely to be malicious.
|
|
64
|
+
*/
|
|
65
|
+
recommendedAction: RecommendedAction;
|
|
66
|
+
/**
|
|
67
|
+
* An optional error message that exists if:
|
|
68
|
+
* - The link requested is not a valid web URL.
|
|
69
|
+
* - Failed to fetch the result from the phishing detector.
|
|
70
|
+
*
|
|
71
|
+
* Consumers can use the existence of this field to retry.
|
|
72
|
+
*/
|
|
73
|
+
fetchError?: string;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Indicates the warning level based on risk factors
|
|
77
|
+
*/
|
|
78
|
+
export declare enum RecommendedAction {
|
|
79
|
+
/**
|
|
80
|
+
* None means it is most likely safe
|
|
81
|
+
*/
|
|
82
|
+
None = "NONE",
|
|
83
|
+
/**
|
|
84
|
+
* Warn means there is some risk
|
|
85
|
+
*/
|
|
86
|
+
Warn = "WARN",
|
|
87
|
+
/**
|
|
88
|
+
* Block means it is highly likely to be malicious
|
|
89
|
+
*/
|
|
90
|
+
Block = "BLOCK"
|
|
91
|
+
}
|
|
50
92
|
//# sourceMappingURL=types.d.cts.map
|
package/dist/types.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.cts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;OAWG;IACH,IAAI,EAAE,0BAA0B,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,oBAAY,0BAA0B;IAIpC,GAAG,QAAQ;IAIX,KAAK,UAAU;IAIf,SAAS,cAAc;IAIvB,SAAS,cAAc;IAKvB,SAAS,cAAc;IAKvB,SAAS,cAAc;IAIvB,iBAAiB,sBAAsB;CACxC"}
|
|
1
|
+
{"version":3,"file":"types.d.cts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;OAWG;IACH,IAAI,EAAE,0BAA0B,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,oBAAY,0BAA0B;IAIpC,GAAG,QAAQ;IAIX,KAAK,UAAU;IAIf,SAAS,cAAc;IAIvB,SAAS,cAAc;IAKvB,SAAS,cAAc;IAKvB,SAAS,cAAc;IAIvB,iBAAiB,sBAAsB;CACxC;AAED;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,iBAAiB,EAAE,iBAAiB,CAAC;IACrC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,oBAAY,iBAAiB;IAC3B;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,KAAK,UAAU;CAChB"}
|
package/dist/types.d.mts
CHANGED
|
@@ -47,4 +47,46 @@ export declare enum PhishingDetectorResultType {
|
|
|
47
47
|
Whitelist = "whitelist",
|
|
48
48
|
C2DomainBlocklist = "c2DomainBlocklist"
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* PhishingDetectionScanResult represents the result of a phishing detection scan.
|
|
52
|
+
*/
|
|
53
|
+
export type PhishingDetectionScanResult = {
|
|
54
|
+
/**
|
|
55
|
+
* The domain name that was scanned.
|
|
56
|
+
*/
|
|
57
|
+
domainName: string;
|
|
58
|
+
/**
|
|
59
|
+
* Indicates the warning level based on risk factors.
|
|
60
|
+
*
|
|
61
|
+
* - "NONE" means it is most likely safe.
|
|
62
|
+
* - "WARN" means there is some risk.
|
|
63
|
+
* - "BLOCK" means it is highly likely to be malicious.
|
|
64
|
+
*/
|
|
65
|
+
recommendedAction: RecommendedAction;
|
|
66
|
+
/**
|
|
67
|
+
* An optional error message that exists if:
|
|
68
|
+
* - The link requested is not a valid web URL.
|
|
69
|
+
* - Failed to fetch the result from the phishing detector.
|
|
70
|
+
*
|
|
71
|
+
* Consumers can use the existence of this field to retry.
|
|
72
|
+
*/
|
|
73
|
+
fetchError?: string;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Indicates the warning level based on risk factors
|
|
77
|
+
*/
|
|
78
|
+
export declare enum RecommendedAction {
|
|
79
|
+
/**
|
|
80
|
+
* None means it is most likely safe
|
|
81
|
+
*/
|
|
82
|
+
None = "NONE",
|
|
83
|
+
/**
|
|
84
|
+
* Warn means there is some risk
|
|
85
|
+
*/
|
|
86
|
+
Warn = "WARN",
|
|
87
|
+
/**
|
|
88
|
+
* Block means it is highly likely to be malicious
|
|
89
|
+
*/
|
|
90
|
+
Block = "BLOCK"
|
|
91
|
+
}
|
|
50
92
|
//# sourceMappingURL=types.d.mts.map
|
package/dist/types.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;OAWG;IACH,IAAI,EAAE,0BAA0B,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,oBAAY,0BAA0B;IAIpC,GAAG,QAAQ;IAIX,KAAK,UAAU;IAIf,SAAS,cAAc;IAIvB,SAAS,cAAc;IAKvB,SAAS,cAAc;IAKvB,SAAS,cAAc;IAIvB,iBAAiB,sBAAsB;CACxC"}
|
|
1
|
+
{"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;OAWG;IACH,IAAI,EAAE,0BAA0B,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,oBAAY,0BAA0B;IAIpC,GAAG,QAAQ;IAIX,KAAK,UAAU;IAIf,SAAS,cAAc;IAIvB,SAAS,cAAc;IAKvB,SAAS,cAAc;IAKvB,SAAS,cAAc;IAIvB,iBAAiB,sBAAsB;CACxC;AAED;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,iBAAiB,EAAE,iBAAiB,CAAC;IACrC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,oBAAY,iBAAiB;IAC3B;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,KAAK,UAAU;CAChB"}
|
package/dist/types.mjs
CHANGED
|
@@ -34,4 +34,22 @@ export var PhishingDetectorResultType;
|
|
|
34
34
|
*/
|
|
35
35
|
PhishingDetectorResultType["C2DomainBlocklist"] = "c2DomainBlocklist";
|
|
36
36
|
})(PhishingDetectorResultType || (PhishingDetectorResultType = {}));
|
|
37
|
+
/**
|
|
38
|
+
* Indicates the warning level based on risk factors
|
|
39
|
+
*/
|
|
40
|
+
export var RecommendedAction;
|
|
41
|
+
(function (RecommendedAction) {
|
|
42
|
+
/**
|
|
43
|
+
* None means it is most likely safe
|
|
44
|
+
*/
|
|
45
|
+
RecommendedAction["None"] = "NONE";
|
|
46
|
+
/**
|
|
47
|
+
* Warn means there is some risk
|
|
48
|
+
*/
|
|
49
|
+
RecommendedAction["Warn"] = "WARN";
|
|
50
|
+
/**
|
|
51
|
+
* Block means it is highly likely to be malicious
|
|
52
|
+
*/
|
|
53
|
+
RecommendedAction["Block"] = "BLOCK";
|
|
54
|
+
})(RecommendedAction || (RecommendedAction = {}));
|
|
37
55
|
//# sourceMappingURL=types.mjs.map
|
package/dist/types.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.mjs","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAsCA;;GAEG;AACH,MAAM,CAAN,IAAY,0BA+BX;AA/BD,WAAY,0BAA0B;IACpC;;OAEG;IACH,yCAAW,CAAA;IACX;;OAEG;IACH,6CAAe,CAAA;IACf;;OAEG;IACH,qDAAuB,CAAA;IACvB;;OAEG;IACH,qDAAuB,CAAA;IACvB;;;OAGG;IACH,qDAAuB,CAAA;IACvB;;;OAGG;IACH,qDAAuB,CAAA;IACvB;;OAEG;IACH,qEAAuC,CAAA;AACzC,CAAC,EA/BW,0BAA0B,KAA1B,0BAA0B,QA+BrC","sourcesContent":["/**\n * Represents the result of checking a domain.\n */\nexport type PhishingDetectorResult = {\n /**\n * The name of the configuration object in which the domain was found within\n * an allowlist, blocklist, or fuzzylist.\n */\n name?: string;\n /**\n * The version associated with the configuration object in which the domain\n * was found within an allowlist, blocklist, or fuzzylist.\n */\n version?: string;\n /**\n * Whether the domain is regarded as allowed (true) or not (false).\n */\n result: boolean;\n /**\n * A normalized version of the domain, which is only constructed if the domain\n * is found within a list.\n */\n match?: string;\n /**\n * Which type of list in which the domain was found.\n *\n * - \"allowlist\" means that the domain was found in the allowlist.\n * - \"blocklist\" means that the domain was found in the blocklist.\n * - \"fuzzy\" means that the domain was found in the fuzzylist.\n * - \"blacklist\" means that the domain was found in a blacklist of a legacy\n * configuration object.\n * - \"whitelist\" means that the domain was found in a whitelist of a legacy\n * configuration object.\n * - \"all\" means that the domain was not found in any list.\n */\n type: PhishingDetectorResultType;\n};\n\n/**\n * The type of list in which the domain was found.\n */\nexport enum PhishingDetectorResultType {\n /*\n * \"all\" means that the domain was not found in any list.\n */\n All = 'all',\n /*\n * \"fuzzy\" means that the domain was found in the fuzzylist.\n */\n Fuzzy = 'fuzzy',\n /*\n * \"blocklist\" means that the domain was found in the blocklist.\n */\n Blocklist = 'blocklist',\n /*\n * \"allowlist\" means that the domain was found in the allowlist.\n */\n Allowlist = 'allowlist',\n /*\n * \"blacklist\" means that the domain was found in a blacklist of a legacy\n * configuration object.\n */\n Blacklist = 'blacklist',\n /*\n * \"whitelist\" means that the domain was found in a whitelist of a legacy\n * configuration object.\n */\n Whitelist = 'whitelist',\n /*\n * \"c2DomainBlocklist\" means that the domain was found in the C2 domain blocklist.\n */\n C2DomainBlocklist = 'c2DomainBlocklist',\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.mjs","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAsCA;;GAEG;AACH,MAAM,CAAN,IAAY,0BA+BX;AA/BD,WAAY,0BAA0B;IACpC;;OAEG;IACH,yCAAW,CAAA;IACX;;OAEG;IACH,6CAAe,CAAA;IACf;;OAEG;IACH,qDAAuB,CAAA;IACvB;;OAEG;IACH,qDAAuB,CAAA;IACvB;;;OAGG;IACH,qDAAuB,CAAA;IACvB;;;OAGG;IACH,qDAAuB,CAAA;IACvB;;OAEG;IACH,qEAAuC,CAAA;AACzC,CAAC,EA/BW,0BAA0B,KAA1B,0BAA0B,QA+BrC;AA4BD;;GAEG;AACH,MAAM,CAAN,IAAY,iBAaX;AAbD,WAAY,iBAAiB;IAC3B;;OAEG;IACH,kCAAa,CAAA;IACb;;OAEG;IACH,kCAAa,CAAA;IACb;;OAEG;IACH,oCAAe,CAAA;AACjB,CAAC,EAbW,iBAAiB,KAAjB,iBAAiB,QAa5B","sourcesContent":["/**\n * Represents the result of checking a domain.\n */\nexport type PhishingDetectorResult = {\n /**\n * The name of the configuration object in which the domain was found within\n * an allowlist, blocklist, or fuzzylist.\n */\n name?: string;\n /**\n * The version associated with the configuration object in which the domain\n * was found within an allowlist, blocklist, or fuzzylist.\n */\n version?: string;\n /**\n * Whether the domain is regarded as allowed (true) or not (false).\n */\n result: boolean;\n /**\n * A normalized version of the domain, which is only constructed if the domain\n * is found within a list.\n */\n match?: string;\n /**\n * Which type of list in which the domain was found.\n *\n * - \"allowlist\" means that the domain was found in the allowlist.\n * - \"blocklist\" means that the domain was found in the blocklist.\n * - \"fuzzy\" means that the domain was found in the fuzzylist.\n * - \"blacklist\" means that the domain was found in a blacklist of a legacy\n * configuration object.\n * - \"whitelist\" means that the domain was found in a whitelist of a legacy\n * configuration object.\n * - \"all\" means that the domain was not found in any list.\n */\n type: PhishingDetectorResultType;\n};\n\n/**\n * The type of list in which the domain was found.\n */\nexport enum PhishingDetectorResultType {\n /*\n * \"all\" means that the domain was not found in any list.\n */\n All = 'all',\n /*\n * \"fuzzy\" means that the domain was found in the fuzzylist.\n */\n Fuzzy = 'fuzzy',\n /*\n * \"blocklist\" means that the domain was found in the blocklist.\n */\n Blocklist = 'blocklist',\n /*\n * \"allowlist\" means that the domain was found in the allowlist.\n */\n Allowlist = 'allowlist',\n /*\n * \"blacklist\" means that the domain was found in a blacklist of a legacy\n * configuration object.\n */\n Blacklist = 'blacklist',\n /*\n * \"whitelist\" means that the domain was found in a whitelist of a legacy\n * configuration object.\n */\n Whitelist = 'whitelist',\n /*\n * \"c2DomainBlocklist\" means that the domain was found in the C2 domain blocklist.\n */\n C2DomainBlocklist = 'c2DomainBlocklist',\n}\n\n/**\n * PhishingDetectionScanResult represents the result of a phishing detection scan.\n */\nexport type PhishingDetectionScanResult = {\n /**\n * The domain name that was scanned.\n */\n domainName: string;\n /**\n * Indicates the warning level based on risk factors.\n *\n * - \"NONE\" means it is most likely safe.\n * - \"WARN\" means there is some risk.\n * - \"BLOCK\" means it is highly likely to be malicious.\n */\n recommendedAction: RecommendedAction;\n /**\n * An optional error message that exists if:\n * - The link requested is not a valid web URL.\n * - Failed to fetch the result from the phishing detector.\n *\n * Consumers can use the existence of this field to retry.\n */\n fetchError?: string;\n};\n\n/**\n * Indicates the warning level based on risk factors\n */\nexport enum RecommendedAction {\n /**\n * None means it is most likely safe\n */\n None = 'NONE',\n /**\n * Warn means there is some risk\n */\n Warn = 'WARN',\n /**\n * Block means it is highly likely to be malicious\n */\n Block = 'BLOCK',\n}\n"]}
|
package/dist/utils.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateParentDomains = exports.getHostnameFromUrl = exports.sha256Hash = exports.matchPartsAgainstList = exports.domainPartsToFuzzyForm = exports.domainPartsToDomain = exports.processConfigs = exports.getDefaultPhishingDetectorConfig = exports.processDomainList = exports.domainToParts = exports.validateConfig = exports.applyDiffs = exports.roundToNearestMinute = exports.fetchTimeNow = void 0;
|
|
3
|
+
exports.generateParentDomains = exports.getHostnameFromWebUrl = exports.getHostnameFromUrl = exports.sha256Hash = exports.matchPartsAgainstList = exports.domainPartsToFuzzyForm = exports.domainPartsToDomain = exports.processConfigs = exports.getDefaultPhishingDetectorConfig = exports.processDomainList = exports.domainToParts = exports.validateConfig = exports.applyDiffs = exports.roundToNearestMinute = exports.fetchTimeNow = void 0;
|
|
4
4
|
const utils_1 = require("@noble/hashes/utils");
|
|
5
5
|
const sha256_1 = require("ethereum-cryptography/sha256");
|
|
6
6
|
const PhishingController_1 = require("./PhishingController.cjs");
|
|
@@ -243,13 +243,38 @@ const getHostnameFromUrl = (url) => {
|
|
|
243
243
|
let hostname;
|
|
244
244
|
try {
|
|
245
245
|
hostname = new URL(url).hostname;
|
|
246
|
+
// above will not throw if 'http://.' is passed. in fact, any string with a dot will pass.
|
|
247
|
+
if (!hostname || hostname.split('.').join('') === '') {
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
246
250
|
}
|
|
247
|
-
catch
|
|
251
|
+
catch {
|
|
248
252
|
return null;
|
|
249
253
|
}
|
|
250
254
|
return hostname;
|
|
251
255
|
};
|
|
252
256
|
exports.getHostnameFromUrl = getHostnameFromUrl;
|
|
257
|
+
/**
|
|
258
|
+
* getHostnameFromWebUrl returns the hostname from a web URL.
|
|
259
|
+
* It returns the hostname and a boolean indicating if the hostname is valid.
|
|
260
|
+
*
|
|
261
|
+
* @param url - The web URL to extract the hostname from.
|
|
262
|
+
* @returns A tuple containing the extracted hostname and a boolean indicating if the hostname is valid.
|
|
263
|
+
* @example
|
|
264
|
+
* getHostnameFromWebUrl('https://example.com') // Returns: ['example.com', true]
|
|
265
|
+
* getHostnameFromWebUrl('example.com') // Returns: ['', false]
|
|
266
|
+
* getHostnameFromWebUrl('https://') // Returns: ['', false]
|
|
267
|
+
* getHostnameFromWebUrl('') // Returns: ['', false]
|
|
268
|
+
*/
|
|
269
|
+
const getHostnameFromWebUrl = (url) => {
|
|
270
|
+
if (!url.toLowerCase().startsWith('http://') &&
|
|
271
|
+
!url.toLowerCase().startsWith('https://')) {
|
|
272
|
+
return ['', false];
|
|
273
|
+
}
|
|
274
|
+
const hostname = (0, exports.getHostnameFromUrl)(url);
|
|
275
|
+
return [hostname || '', Boolean(hostname)];
|
|
276
|
+
};
|
|
277
|
+
exports.getHostnameFromWebUrl = getHostnameFromWebUrl;
|
|
253
278
|
/**
|
|
254
279
|
* Generates all possible parent domains up to a specified limit.
|
|
255
280
|
*
|
package/dist/utils.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.cjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToHex } from '@noble/hashes/utils';\nimport { sha256 } from 'ethereum-cryptography/sha256';\n\nimport type { Hotlist, PhishingListState } from './PhishingController';\nimport { ListKeys, phishingListKeyNameMap } from './PhishingController';\nimport type {\n PhishingDetectorList,\n PhishingDetectorConfiguration,\n} from './PhishingDetector';\n\nconst DEFAULT_TOLERANCE = 3;\n\n/**\n * Fetches current epoch time in seconds.\n *\n * @returns the Date.now() time in seconds instead of miliseconds. backend files rely on timestamps in seconds since epoch.\n */\nexport const fetchTimeNow = (): number => Math.round(Date.now() / 1000);\n\n/**\n * Rounds a Unix timestamp down to the nearest minute.\n *\n * @param unixTimestamp - The Unix timestamp to be rounded.\n * @returns The rounded Unix timestamp.\n */\nexport function roundToNearestMinute(unixTimestamp: number): number {\n return Math.floor(unixTimestamp / 60) * 60;\n}\n\n/**\n * Split a string into two pieces, using the first period as the delimiter.\n *\n * @param stringToSplit - The string to split.\n * @returns An array of length two containing the beginning and end of the string.\n */\nconst splitStringByPeriod = <Start extends string, End extends string>(\n stringToSplit: `${Start}.${End}`,\n): [Start, End] => {\n const periodIndex = stringToSplit.indexOf('.');\n return [\n stringToSplit.slice(0, periodIndex) as Start,\n stringToSplit.slice(periodIndex + 1) as End,\n ];\n};\n\n/**\n * Determines which diffs are applicable to the listState, then applies those diffs.\n *\n * @param listState - the stalelist or the existing liststate that diffs will be applied to.\n * @param hotlistDiffs - the diffs to apply to the listState if valid.\n * @param listKey - the key associated with the input/output phishing list state.\n * @param recentlyAddedC2Domains - list of hashed C2 domains to add to the local c2 domain blocklist\n * @param recentlyRemovedC2Domains - list of hashed C2 domains to remove from the local c2 domain blocklist\n * @returns the new list state\n */\nexport const applyDiffs = (\n listState: PhishingListState,\n hotlistDiffs: Hotlist,\n listKey: ListKeys,\n recentlyAddedC2Domains: string[] = [],\n recentlyRemovedC2Domains: string[] = [],\n): PhishingListState => {\n // filter to remove diffs that were added before the lastUpdate time.\n // filter to remove diffs that aren't applicable to the specified list (by listKey).\n const diffsToApply = hotlistDiffs.filter(\n ({ timestamp, targetList }) =>\n timestamp > listState.lastUpdated &&\n splitStringByPeriod(targetList)[0] === listKey,\n );\n\n // the reason behind using latestDiffTimestamp as the lastUpdated time\n // is so that we can benefit server-side from memoization due to end client's\n // `GET /v1/diffSince/:timestamp` requests lining up with\n // our periodic updates (which create diffs at specific timestamps).\n let latestDiffTimestamp = listState.lastUpdated;\n\n const listSets = {\n allowlist: new Set(listState.allowlist),\n blocklist: new Set(listState.blocklist),\n fuzzylist: new Set(listState.fuzzylist),\n c2DomainBlocklist: new Set(listState.c2DomainBlocklist),\n };\n for (const { isRemoval, targetList, url, timestamp } of diffsToApply) {\n const targetListType = splitStringByPeriod(targetList)[1];\n if (timestamp > latestDiffTimestamp) {\n latestDiffTimestamp = timestamp;\n }\n if (isRemoval) {\n listSets[targetListType].delete(url);\n } else {\n listSets[targetListType].add(url);\n }\n }\n\n if (listKey === ListKeys.EthPhishingDetectConfig) {\n for (const hash of recentlyAddedC2Domains) {\n listSets.c2DomainBlocklist.add(hash);\n }\n for (const hash of recentlyRemovedC2Domains) {\n listSets.c2DomainBlocklist.delete(hash);\n }\n }\n\n return {\n c2DomainBlocklist: Array.from(listSets.c2DomainBlocklist),\n allowlist: Array.from(listSets.allowlist),\n blocklist: Array.from(listSets.blocklist),\n fuzzylist: Array.from(listSets.fuzzylist),\n version: listState.version,\n name: phishingListKeyNameMap[listKey],\n tolerance: listState.tolerance,\n lastUpdated: latestDiffTimestamp,\n };\n};\n\n/**\n * Validates the configuration object for the phishing detector.\n *\n * @param config - the configuration object to validate.\n * @throws an error if the configuration is invalid.\n */\nexport function validateConfig(\n config: unknown,\n): asserts config is PhishingListState {\n if (config === null || typeof config !== 'object') {\n throw new Error('Invalid config');\n }\n\n if ('tolerance' in config && !('fuzzylist' in config)) {\n throw new Error('Fuzzylist tolerance provided without fuzzylist');\n }\n\n if (\n 'name' in config &&\n (typeof config.name !== 'string' || config.name === '')\n ) {\n throw new Error(\"Invalid config parameter: 'name'\");\n }\n\n if (\n 'version' in config &&\n (!['number', 'string'].includes(typeof config.version) ||\n config.version === '')\n ) {\n throw new Error(\"Invalid config parameter: 'version'\");\n }\n}\n\n/**\n * Converts a domain string to a list of domain parts.\n *\n * @param domain - the domain string to convert.\n * @returns the list of domain parts.\n */\nexport const domainToParts = (domain: string) => {\n try {\n return domain.split('.').reverse();\n } catch (e) {\n throw new Error(JSON.stringify(domain));\n }\n};\n\n/**\n * Converts a list of domain strings to a list of domain parts.\n *\n * @param list - the list of domain strings to convert.\n * @returns the list of domain parts.\n */\nexport const processDomainList = (list: string[]) => {\n return list.map(domainToParts);\n};\n\n/**\n * Gets the default phishing detector configuration.\n *\n * @param override - the optional override for the configuration.\n * @param override.allowlist - the optional allowlist to override.\n * @param override.blocklist - the optional blocklist to override.\n * @param override.c2DomainBlocklist - the optional c2DomainBlocklist to override.\n * @param override.fuzzylist - the optional fuzzylist to override.\n * @param override.tolerance - the optional tolerance to override.\n * @returns the default phishing detector configuration.\n */\nexport const getDefaultPhishingDetectorConfig = ({\n allowlist = [],\n blocklist = [],\n fuzzylist = [],\n tolerance = DEFAULT_TOLERANCE,\n}: {\n allowlist?: string[];\n blocklist?: string[];\n c2DomainBlocklist?: string[];\n fuzzylist?: string[];\n tolerance?: number;\n}): PhishingDetectorConfiguration => ({\n allowlist: processDomainList(allowlist),\n blocklist: processDomainList(blocklist),\n fuzzylist: processDomainList(fuzzylist),\n tolerance,\n});\n\n/**\n * Processes the configurations for the phishing detector, filtering out any invalid configs.\n *\n * @param configs - The configurations to process.\n * @returns An array of processed and valid configurations.\n */\nexport const processConfigs = (\n configs: PhishingDetectorList[] = [],\n): PhishingDetectorConfiguration[] => {\n return configs\n .filter((config) => {\n try {\n validateConfig(config);\n return true;\n } catch (error) {\n console.error(error);\n return false;\n }\n })\n .map((config) => ({\n ...config,\n ...getDefaultPhishingDetectorConfig(config),\n }));\n};\n\n/**\n * Converts a list of domain parts to a domain string.\n *\n * @param domainParts - the list of domain parts.\n * @returns the domain string.\n */\nexport const domainPartsToDomain = (domainParts: string[]) => {\n return domainParts.slice().reverse().join('.');\n};\n\n/**\n * Converts a list of domain parts to a fuzzy form.\n *\n * @param domainParts - the list of domain parts.\n * @returns the fuzzy form of the domain.\n */\nexport const domainPartsToFuzzyForm = (domainParts: string[]) => {\n return domainParts.slice(1).reverse().join('.');\n};\n\n/**\n * Matches the target parts, ignoring extra subdomains on source.\n *\n * @param source - the source domain parts.\n * @param list - the list of domain parts to match against.\n * @returns the parts for the first found matching entry.\n */\nexport const matchPartsAgainstList = (source: string[], list: string[][]) => {\n return list.find((target) => {\n // target domain has more parts than source, fail\n if (target.length > source.length) {\n return false;\n }\n // source matches target or (is deeper subdomain)\n return target.every((part, index) => source[index] === part);\n });\n};\n\n/**\n * Generate the SHA-256 hash of a hostname.\n *\n * @param hostname - The hostname to hash.\n * @returns The SHA-256 hash of the hostname.\n */\nexport const sha256Hash = (hostname: string): string => {\n const hashBuffer = sha256(new TextEncoder().encode(hostname.toLowerCase()));\n return bytesToHex(hashBuffer);\n};\n\n/**\n * Extracts the hostname from a URL.\n *\n * @param url - The URL to extract the hostname from.\n * @returns The hostname extracted from the URL, or null if the URL is invalid.\n */\nexport const getHostnameFromUrl = (url: string): string | null => {\n let hostname;\n try {\n hostname = new URL(url).hostname;\n } catch (error) {\n return null;\n }\n return hostname;\n};\n\n/**\n * Generates all possible parent domains up to a specified limit.\n *\n * @param sourceParts - The list of domain parts in normal order (e.g., ['evil', 'domain', 'co', 'uk']).\n * @param limit - The maximum number of parent domains to generate (default is 5).\n * @returns An array of parent domains starting from the base TLD to the most specific subdomain.\n * @example\n * generateParentDomains(['evil', 'domain', 'co', 'uk'], 5)\n * // Returns: ['co.uk', 'domain.co.uk', 'evil.domain.co.uk']\n *\n * generateParentDomains(['uk'], 5)\n * // Returns: ['uk']\n *\n * generateParentDomains(['sub', 'example', 'com'], 5)\n * // Returns: ['example.com', 'sub.example.com']\n */\nexport const generateParentDomains = (\n sourceParts: string[],\n limit = 5,\n): string[] => {\n const domains: string[] = [];\n\n if (sourceParts.length === 0) {\n return domains;\n }\n\n if (sourceParts.length === 1) {\n // Single-segment hostname (e.g., 'uk')\n domains.push(sourceParts[0].toLowerCase());\n } else {\n // Start with the base domain or TLD (last two labels, e.g., 'co.uk' or 'example.com')\n const baseDomain = sourceParts.slice(-2).join('.');\n domains.push(baseDomain.toLowerCase());\n\n // Iteratively add one subdomain level at a time, up to the specified limit\n for (\n let i = sourceParts.length - 3;\n i >= 0 && domains.length < limit;\n i--\n ) {\n const domain = sourceParts.slice(i).join('.');\n domains.push(domain.toLowerCase());\n }\n }\n\n return domains;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"utils.cjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToHex } from '@noble/hashes/utils';\nimport { sha256 } from 'ethereum-cryptography/sha256';\n\nimport type { Hotlist, PhishingListState } from './PhishingController';\nimport { ListKeys, phishingListKeyNameMap } from './PhishingController';\nimport type {\n PhishingDetectorList,\n PhishingDetectorConfiguration,\n} from './PhishingDetector';\n\nconst DEFAULT_TOLERANCE = 3;\n\n/**\n * Fetches current epoch time in seconds.\n *\n * @returns the Date.now() time in seconds instead of miliseconds. backend files rely on timestamps in seconds since epoch.\n */\nexport const fetchTimeNow = (): number => Math.round(Date.now() / 1000);\n\n/**\n * Rounds a Unix timestamp down to the nearest minute.\n *\n * @param unixTimestamp - The Unix timestamp to be rounded.\n * @returns The rounded Unix timestamp.\n */\nexport function roundToNearestMinute(unixTimestamp: number): number {\n return Math.floor(unixTimestamp / 60) * 60;\n}\n\n/**\n * Split a string into two pieces, using the first period as the delimiter.\n *\n * @param stringToSplit - The string to split.\n * @returns An array of length two containing the beginning and end of the string.\n */\nconst splitStringByPeriod = <Start extends string, End extends string>(\n stringToSplit: `${Start}.${End}`,\n): [Start, End] => {\n const periodIndex = stringToSplit.indexOf('.');\n return [\n stringToSplit.slice(0, periodIndex) as Start,\n stringToSplit.slice(periodIndex + 1) as End,\n ];\n};\n\n/**\n * Determines which diffs are applicable to the listState, then applies those diffs.\n *\n * @param listState - the stalelist or the existing liststate that diffs will be applied to.\n * @param hotlistDiffs - the diffs to apply to the listState if valid.\n * @param listKey - the key associated with the input/output phishing list state.\n * @param recentlyAddedC2Domains - list of hashed C2 domains to add to the local c2 domain blocklist\n * @param recentlyRemovedC2Domains - list of hashed C2 domains to remove from the local c2 domain blocklist\n * @returns the new list state\n */\nexport const applyDiffs = (\n listState: PhishingListState,\n hotlistDiffs: Hotlist,\n listKey: ListKeys,\n recentlyAddedC2Domains: string[] = [],\n recentlyRemovedC2Domains: string[] = [],\n): PhishingListState => {\n // filter to remove diffs that were added before the lastUpdate time.\n // filter to remove diffs that aren't applicable to the specified list (by listKey).\n const diffsToApply = hotlistDiffs.filter(\n ({ timestamp, targetList }) =>\n timestamp > listState.lastUpdated &&\n splitStringByPeriod(targetList)[0] === listKey,\n );\n\n // the reason behind using latestDiffTimestamp as the lastUpdated time\n // is so that we can benefit server-side from memoization due to end client's\n // `GET /v1/diffSince/:timestamp` requests lining up with\n // our periodic updates (which create diffs at specific timestamps).\n let latestDiffTimestamp = listState.lastUpdated;\n\n const listSets = {\n allowlist: new Set(listState.allowlist),\n blocklist: new Set(listState.blocklist),\n fuzzylist: new Set(listState.fuzzylist),\n c2DomainBlocklist: new Set(listState.c2DomainBlocklist),\n };\n for (const { isRemoval, targetList, url, timestamp } of diffsToApply) {\n const targetListType = splitStringByPeriod(targetList)[1];\n if (timestamp > latestDiffTimestamp) {\n latestDiffTimestamp = timestamp;\n }\n if (isRemoval) {\n listSets[targetListType].delete(url);\n } else {\n listSets[targetListType].add(url);\n }\n }\n\n if (listKey === ListKeys.EthPhishingDetectConfig) {\n for (const hash of recentlyAddedC2Domains) {\n listSets.c2DomainBlocklist.add(hash);\n }\n for (const hash of recentlyRemovedC2Domains) {\n listSets.c2DomainBlocklist.delete(hash);\n }\n }\n\n return {\n c2DomainBlocklist: Array.from(listSets.c2DomainBlocklist),\n allowlist: Array.from(listSets.allowlist),\n blocklist: Array.from(listSets.blocklist),\n fuzzylist: Array.from(listSets.fuzzylist),\n version: listState.version,\n name: phishingListKeyNameMap[listKey],\n tolerance: listState.tolerance,\n lastUpdated: latestDiffTimestamp,\n };\n};\n\n/**\n * Validates the configuration object for the phishing detector.\n *\n * @param config - the configuration object to validate.\n * @throws an error if the configuration is invalid.\n */\nexport function validateConfig(\n config: unknown,\n): asserts config is PhishingListState {\n if (config === null || typeof config !== 'object') {\n throw new Error('Invalid config');\n }\n\n if ('tolerance' in config && !('fuzzylist' in config)) {\n throw new Error('Fuzzylist tolerance provided without fuzzylist');\n }\n\n if (\n 'name' in config &&\n (typeof config.name !== 'string' || config.name === '')\n ) {\n throw new Error(\"Invalid config parameter: 'name'\");\n }\n\n if (\n 'version' in config &&\n (!['number', 'string'].includes(typeof config.version) ||\n config.version === '')\n ) {\n throw new Error(\"Invalid config parameter: 'version'\");\n }\n}\n\n/**\n * Converts a domain string to a list of domain parts.\n *\n * @param domain - the domain string to convert.\n * @returns the list of domain parts.\n */\nexport const domainToParts = (domain: string) => {\n try {\n return domain.split('.').reverse();\n } catch (e) {\n throw new Error(JSON.stringify(domain));\n }\n};\n\n/**\n * Converts a list of domain strings to a list of domain parts.\n *\n * @param list - the list of domain strings to convert.\n * @returns the list of domain parts.\n */\nexport const processDomainList = (list: string[]) => {\n return list.map(domainToParts);\n};\n\n/**\n * Gets the default phishing detector configuration.\n *\n * @param override - the optional override for the configuration.\n * @param override.allowlist - the optional allowlist to override.\n * @param override.blocklist - the optional blocklist to override.\n * @param override.c2DomainBlocklist - the optional c2DomainBlocklist to override.\n * @param override.fuzzylist - the optional fuzzylist to override.\n * @param override.tolerance - the optional tolerance to override.\n * @returns the default phishing detector configuration.\n */\nexport const getDefaultPhishingDetectorConfig = ({\n allowlist = [],\n blocklist = [],\n fuzzylist = [],\n tolerance = DEFAULT_TOLERANCE,\n}: {\n allowlist?: string[];\n blocklist?: string[];\n c2DomainBlocklist?: string[];\n fuzzylist?: string[];\n tolerance?: number;\n}): PhishingDetectorConfiguration => ({\n allowlist: processDomainList(allowlist),\n blocklist: processDomainList(blocklist),\n fuzzylist: processDomainList(fuzzylist),\n tolerance,\n});\n\n/**\n * Processes the configurations for the phishing detector, filtering out any invalid configs.\n *\n * @param configs - The configurations to process.\n * @returns An array of processed and valid configurations.\n */\nexport const processConfigs = (\n configs: PhishingDetectorList[] = [],\n): PhishingDetectorConfiguration[] => {\n return configs\n .filter((config) => {\n try {\n validateConfig(config);\n return true;\n } catch (error) {\n console.error(error);\n return false;\n }\n })\n .map((config) => ({\n ...config,\n ...getDefaultPhishingDetectorConfig(config),\n }));\n};\n\n/**\n * Converts a list of domain parts to a domain string.\n *\n * @param domainParts - the list of domain parts.\n * @returns the domain string.\n */\nexport const domainPartsToDomain = (domainParts: string[]) => {\n return domainParts.slice().reverse().join('.');\n};\n\n/**\n * Converts a list of domain parts to a fuzzy form.\n *\n * @param domainParts - the list of domain parts.\n * @returns the fuzzy form of the domain.\n */\nexport const domainPartsToFuzzyForm = (domainParts: string[]) => {\n return domainParts.slice(1).reverse().join('.');\n};\n\n/**\n * Matches the target parts, ignoring extra subdomains on source.\n *\n * @param source - the source domain parts.\n * @param list - the list of domain parts to match against.\n * @returns the parts for the first found matching entry.\n */\nexport const matchPartsAgainstList = (source: string[], list: string[][]) => {\n return list.find((target) => {\n // target domain has more parts than source, fail\n if (target.length > source.length) {\n return false;\n }\n // source matches target or (is deeper subdomain)\n return target.every((part, index) => source[index] === part);\n });\n};\n\n/**\n * Generate the SHA-256 hash of a hostname.\n *\n * @param hostname - The hostname to hash.\n * @returns The SHA-256 hash of the hostname.\n */\nexport const sha256Hash = (hostname: string): string => {\n const hashBuffer = sha256(new TextEncoder().encode(hostname.toLowerCase()));\n return bytesToHex(hashBuffer);\n};\n\n/**\n * Extracts the hostname from a URL.\n *\n * @param url - The URL to extract the hostname from.\n * @returns The hostname extracted from the URL, or null if the URL is invalid.\n */\nexport const getHostnameFromUrl = (url: string): string | null => {\n let hostname;\n try {\n hostname = new URL(url).hostname;\n // above will not throw if 'http://.' is passed. in fact, any string with a dot will pass.\n if (!hostname || hostname.split('.').join('') === '') {\n return null;\n }\n } catch {\n return null;\n }\n return hostname;\n};\n\n/**\n * getHostnameFromWebUrl returns the hostname from a web URL.\n * It returns the hostname and a boolean indicating if the hostname is valid.\n *\n * @param url - The web URL to extract the hostname from.\n * @returns A tuple containing the extracted hostname and a boolean indicating if the hostname is valid.\n * @example\n * getHostnameFromWebUrl('https://example.com') // Returns: ['example.com', true]\n * getHostnameFromWebUrl('example.com') // Returns: ['', false]\n * getHostnameFromWebUrl('https://') // Returns: ['', false]\n * getHostnameFromWebUrl('') // Returns: ['', false]\n */\nexport const getHostnameFromWebUrl = (url: string): [string, boolean] => {\n if (\n !url.toLowerCase().startsWith('http://') &&\n !url.toLowerCase().startsWith('https://')\n ) {\n return ['', false];\n }\n\n const hostname = getHostnameFromUrl(url);\n return [hostname || '', Boolean(hostname)];\n};\n\n/**\n * Generates all possible parent domains up to a specified limit.\n *\n * @param sourceParts - The list of domain parts in normal order (e.g., ['evil', 'domain', 'co', 'uk']).\n * @param limit - The maximum number of parent domains to generate (default is 5).\n * @returns An array of parent domains starting from the base TLD to the most specific subdomain.\n * @example\n * generateParentDomains(['evil', 'domain', 'co', 'uk'], 5)\n * // Returns: ['co.uk', 'domain.co.uk', 'evil.domain.co.uk']\n *\n * generateParentDomains(['uk'], 5)\n * // Returns: ['uk']\n *\n * generateParentDomains(['sub', 'example', 'com'], 5)\n * // Returns: ['example.com', 'sub.example.com']\n */\nexport const generateParentDomains = (\n sourceParts: string[],\n limit = 5,\n): string[] => {\n const domains: string[] = [];\n\n if (sourceParts.length === 0) {\n return domains;\n }\n\n if (sourceParts.length === 1) {\n // Single-segment hostname (e.g., 'uk')\n domains.push(sourceParts[0].toLowerCase());\n } else {\n // Start with the base domain or TLD (last two labels, e.g., 'co.uk' or 'example.com')\n const baseDomain = sourceParts.slice(-2).join('.');\n domains.push(baseDomain.toLowerCase());\n\n // Iteratively add one subdomain level at a time, up to the specified limit\n for (\n let i = sourceParts.length - 3;\n i >= 0 && domains.length < limit;\n i--\n ) {\n const domain = sourceParts.slice(i).join('.');\n domains.push(domain.toLowerCase());\n }\n }\n\n return domains;\n};\n"]}
|
package/dist/utils.d.cts
CHANGED
|
@@ -107,6 +107,19 @@ export declare const sha256Hash: (hostname: string) => string;
|
|
|
107
107
|
* @returns The hostname extracted from the URL, or null if the URL is invalid.
|
|
108
108
|
*/
|
|
109
109
|
export declare const getHostnameFromUrl: (url: string) => string | null;
|
|
110
|
+
/**
|
|
111
|
+
* getHostnameFromWebUrl returns the hostname from a web URL.
|
|
112
|
+
* It returns the hostname and a boolean indicating if the hostname is valid.
|
|
113
|
+
*
|
|
114
|
+
* @param url - The web URL to extract the hostname from.
|
|
115
|
+
* @returns A tuple containing the extracted hostname and a boolean indicating if the hostname is valid.
|
|
116
|
+
* @example
|
|
117
|
+
* getHostnameFromWebUrl('https://example.com') // Returns: ['example.com', true]
|
|
118
|
+
* getHostnameFromWebUrl('example.com') // Returns: ['', false]
|
|
119
|
+
* getHostnameFromWebUrl('https://') // Returns: ['', false]
|
|
120
|
+
* getHostnameFromWebUrl('') // Returns: ['', false]
|
|
121
|
+
*/
|
|
122
|
+
export declare const getHostnameFromWebUrl: (url: string) => [string, boolean];
|
|
110
123
|
/**
|
|
111
124
|
* Generates all possible parent domains up to a specified limit.
|
|
112
125
|
*
|
package/dist/utils.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.cts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,iCAA6B;AACvE,OAAO,EAAE,QAAQ,EAA0B,iCAA6B;AACxE,OAAO,KAAK,EACV,oBAAoB,EACpB,6BAA6B,EAC9B,+BAA2B;AAI5B;;;;GAIG;AACH,eAAO,MAAM,YAAY,QAAO,MAAuC,CAAC;AAExE;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAElE;AAkBD;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,cACV,iBAAiB,kCAEnB,QAAQ,2BACO,MAAM,EAAE,6BACN,MAAM,EAAE,KACjC,iBAoDF,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,MAAM,IAAI,iBAAiB,CAuBrC;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,WAAY,MAAM,aAM3C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,SAAU,MAAM,EAAE,eAE/C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gCAAgC;;;;;;MAWzC,6BAKF,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,aAChB,oBAAoB,EAAE,KAC9B,6BAA6B,EAe/B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,gBAAiB,MAAM,EAAE,WAExD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,gBAAiB,MAAM,EAAE,WAE3D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,WAAY,MAAM,EAAE,QAAQ,MAAM,EAAE,EAAE,yBASvE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,aAAc,MAAM,KAAG,MAG7C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,QAAS,MAAM,KAAG,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"utils.d.cts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,iCAA6B;AACvE,OAAO,EAAE,QAAQ,EAA0B,iCAA6B;AACxE,OAAO,KAAK,EACV,oBAAoB,EACpB,6BAA6B,EAC9B,+BAA2B;AAI5B;;;;GAIG;AACH,eAAO,MAAM,YAAY,QAAO,MAAuC,CAAC;AAExE;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAElE;AAkBD;;;;;;;;;GASG;AACH,eAAO,MAAM,UAAU,cACV,iBAAiB,kCAEnB,QAAQ,2BACO,MAAM,EAAE,6BACN,MAAM,EAAE,KACjC,iBAoDF,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,OAAO,GACd,OAAO,CAAC,MAAM,IAAI,iBAAiB,CAuBrC;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,WAAY,MAAM,aAM3C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,SAAU,MAAM,EAAE,eAE/C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gCAAgC;;;;;;MAWzC,6BAKF,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,cAAc,aAChB,oBAAoB,EAAE,KAC9B,6BAA6B,EAe/B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,gBAAiB,MAAM,EAAE,WAExD,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,gBAAiB,MAAM,EAAE,WAE3D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,WAAY,MAAM,EAAE,QAAQ,MAAM,EAAE,EAAE,yBASvE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,UAAU,aAAc,MAAM,KAAG,MAG7C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,QAAS,MAAM,KAAG,MAAM,GAAG,IAYzD,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,QAAS,MAAM,KAAG,CAAC,MAAM,EAAE,OAAO,CAUnE,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB,gBACnB,MAAM,EAAE,qBAEpB,MAAM,EA2BR,CAAC"}
|
package/dist/utils.d.mts
CHANGED
|
@@ -107,6 +107,19 @@ export declare const sha256Hash: (hostname: string) => string;
|
|
|
107
107
|
* @returns The hostname extracted from the URL, or null if the URL is invalid.
|
|
108
108
|
*/
|
|
109
109
|
export declare const getHostnameFromUrl: (url: string) => string | null;
|
|
110
|
+
/**
|
|
111
|
+
* getHostnameFromWebUrl returns the hostname from a web URL.
|
|
112
|
+
* It returns the hostname and a boolean indicating if the hostname is valid.
|
|
113
|
+
*
|
|
114
|
+
* @param url - The web URL to extract the hostname from.
|
|
115
|
+
* @returns A tuple containing the extracted hostname and a boolean indicating if the hostname is valid.
|
|
116
|
+
* @example
|
|
117
|
+
* getHostnameFromWebUrl('https://example.com') // Returns: ['example.com', true]
|
|
118
|
+
* getHostnameFromWebUrl('example.com') // Returns: ['', false]
|
|
119
|
+
* getHostnameFromWebUrl('https://') // Returns: ['', false]
|
|
120
|
+
* getHostnameFromWebUrl('') // Returns: ['', false]
|
|
121
|
+
*/
|
|
122
|
+
export declare const getHostnameFromWebUrl: (url: string) => [string, boolean];
|
|
110
123
|
/**
|
|
111
124
|
* Generates all possible parent domains up to a specified limit.
|
|
112
125
|
*
|