Socket
Socket
Sign inDemoInstall

@metamask/phishing-controller

Package Overview
Dependencies
Maintainers
8
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@metamask/phishing-controller - npm Package Compare versions

Comparing version 3.0.0 to 4.0.0

dist/index.d.ts.map

12

CHANGELOG.md

@@ -9,2 +9,11 @@ # Changelog

## [4.0.0]
### Changed
- **BREAKING:** Switch to new phishing configuration API that returns a diff since the last update ([#1123](https://github.com/MetaMask/core/pull/1123))
- The "hotlist" has been replaced by a service that returns any configuration changes since the last update. This should reduce network traffic even further.
- The endpoints used are now `https://phishing-detection.metafi.codefi.network/v1/stalelist` and `https://phishing-detection.metafi.codefi.network/v1/diffsSince/:lastUpdated`
- **BREAKING:**: The phishing controller state now keeps the MetaMask and PhishFort configuration separate, allowing for proper attribution of each block ([#1123](https://github.com/MetaMask/core/pull/1123))
- The `listState` state property has been replaced with an array of phishing list state objects (one entry for MetaMask, one for PhishFort).
- The PhishFort config is deduplicated server-side, so it should have zero overlap with the MetaMask configuration (which helps reduce memory/disk usage)
## [3.0.0]

@@ -61,3 +70,4 @@ ### Removed

[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/phishing-controller@3.0.0...HEAD
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/phishing-controller@4.0.0...HEAD
[4.0.0]: https://github.com/MetaMask/core/compare/@metamask/phishing-controller@3.0.0...@metamask/phishing-controller@4.0.0
[3.0.0]: https://github.com/MetaMask/core/compare/@metamask/phishing-controller@2.0.0...@metamask/phishing-controller@3.0.0

@@ -64,0 +74,0 @@ [2.0.0]: https://github.com/MetaMask/core/compare/@metamask/phishing-controller@1.1.2...@metamask/phishing-controller@2.0.0

export * from './PhishingController';
//# sourceMappingURL=index.d.ts.map

56

dist/PhishingController.d.ts
import { BaseController, BaseConfig, BaseState } from '@metamask/base-controller';
/**
* @type ListTypes
*
* Type outlining the types of lists provided by aggregating different source lists
*/
export declare type ListTypes = 'fuzzylist' | 'blocklist' | 'allowlist';
/**
* @type EthPhishingResponse

@@ -24,5 +30,4 @@ *

* Interface defining expected type of the stalelist.json file.
* @property allowlist - List of approved origins (legacy naming "whitelist")
* @property blocklist - List of unapproved origins (legacy naming "blacklist")
* @property fuzzylist - List of fuzzy-matched unapproved origins
* @property eth_phishing_detect_config - Stale list sourced from eth-phishing-detect's config.json.
* @property phishfort_hotlist - Stale list sourced from phishfort's hotlist.json. Only includes blocklist. Deduplicated entries from eth_phishing_detect_config.
* @property tolerance - Fuzzy match tolerance level

@@ -33,5 +38,4 @@ * @property lastUpdated - Timestamp of last update.

export interface PhishingStalelist {
allowlist: string[];
blocklist: string[];
fuzzylist: string[];
eth_phishing_detect_config: Record<ListTypes, string[]>;
phishfort_hotlist: Record<ListTypes, string[]>;
tolerance: number;

@@ -51,2 +55,3 @@ version: number;

* @property version - Version of the phishing list state.
* @property name - Name of the list. Used for attribution.
*/

@@ -60,3 +65,3 @@ export interface PhishingListState {

lastUpdated: number;
name: string;
name: ListNames;
}

@@ -92,5 +97,8 @@ /**

timestamp: number;
targetList: 'fuzzylist' | 'blocklist' | 'allowlist';
targetList: `${ListKeys}.${ListTypes}`;
isRemoval?: boolean;
}
export interface DataResultWrapper<T> {
data: T;
}
/**

@@ -125,3 +133,3 @@ * @type Hotlist

export interface PhishingState extends BaseState {
listState: PhishingListState;
phishingLists: PhishingListState[];
whitelist: string[];

@@ -131,5 +139,5 @@ hotlistLastFetched: number;

}
export declare const PHISHING_CONFIG_BASE_URL = "https://static.metafi.codefi.network/api/v1/lists";
export declare const METAMASK_STALELIST_FILE = "/stalelist.json";
export declare const METAMASK_HOTLIST_DIFF_FILE = "/hotlist.json";
export declare const PHISHING_CONFIG_BASE_URL = "https://phishing-detection.metafi.codefi.network";
export declare const METAMASK_STALELIST_FILE = "/v1/stalelist";
export declare const METAMASK_HOTLIST_DIFF_FILE = "/v1/diffsSince";
export declare const HOTLIST_REFRESH_INTERVAL: number;

@@ -140,2 +148,25 @@ export declare const STALELIST_REFRESH_INTERVAL: number;

/**
* Enum containing upstream data provider source list keys.
* These are the keys denoting lists consumed by the upstream data provider.
*/
export declare enum ListKeys {
PhishfortHotlist = "phishfort_hotlist",
EthPhishingDetectConfig = "eth_phishing_detect_config"
}
/**
* Enum containing downstream client attribution names.
*/
export declare enum ListNames {
MetaMask = "MetaMask",
Phishfort = "Phishfort"
}
/**
* Maps from list key sourced from upstream data
* provider to downstream client attribution name.
*/
export declare const phishingListKeyNameMap: {
eth_phishing_detect_config: ListNames;
phishfort_hotlist: ListNames;
};
/**
* Controller that manages community-maintained lists of approved and unapproved website origins.

@@ -232,1 +263,2 @@ */

export default PhishingController;
//# sourceMappingURL=PhishingController.d.ts.map

@@ -22,2 +22,13 @@ "use strict";

};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -28,3 +39,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

Object.defineProperty(exports, "__esModule", { value: true });
exports.PhishingController = exports.METAMASK_HOTLIST_DIFF_URL = exports.METAMASK_STALELIST_URL = exports.STALELIST_REFRESH_INTERVAL = exports.HOTLIST_REFRESH_INTERVAL = exports.METAMASK_HOTLIST_DIFF_FILE = exports.METAMASK_STALELIST_FILE = exports.PHISHING_CONFIG_BASE_URL = void 0;
exports.PhishingController = exports.phishingListKeyNameMap = exports.ListNames = exports.ListKeys = exports.METAMASK_HOTLIST_DIFF_URL = exports.METAMASK_STALELIST_URL = exports.STALELIST_REFRESH_INTERVAL = exports.HOTLIST_REFRESH_INTERVAL = exports.METAMASK_HOTLIST_DIFF_FILE = exports.METAMASK_STALELIST_FILE = exports.PHISHING_CONFIG_BASE_URL = void 0;
const punycode_1 = require("punycode/");

@@ -36,5 +47,5 @@ const config_json_1 = __importDefault(require("eth-phishing-detect/src/config.json"));

const utils_1 = require("./utils");
exports.PHISHING_CONFIG_BASE_URL = 'https://static.metafi.codefi.network/api/v1/lists';
exports.METAMASK_STALELIST_FILE = '/stalelist.json';
exports.METAMASK_HOTLIST_DIFF_FILE = '/hotlist.json';
exports.PHISHING_CONFIG_BASE_URL = 'https://phishing-detection.metafi.codefi.network';
exports.METAMASK_STALELIST_FILE = '/v1/stalelist';
exports.METAMASK_HOTLIST_DIFF_FILE = '/v1/diffsSince';
exports.HOTLIST_REFRESH_INTERVAL = 30 * 60; // 30 mins in seconds

@@ -45,2 +56,35 @@ exports.STALELIST_REFRESH_INTERVAL = 4 * 24 * 60 * 60; // 4 days in seconds

/**
* Enum containing upstream data provider source list keys.
* These are the keys denoting lists consumed by the upstream data provider.
*/
var ListKeys;
(function (ListKeys) {
ListKeys["PhishfortHotlist"] = "phishfort_hotlist";
ListKeys["EthPhishingDetectConfig"] = "eth_phishing_detect_config";
})(ListKeys = exports.ListKeys || (exports.ListKeys = {}));
/**
* Enum containing downstream client attribution names.
*/
var ListNames;
(function (ListNames) {
ListNames["MetaMask"] = "MetaMask";
ListNames["Phishfort"] = "Phishfort";
})(ListNames = exports.ListNames || (exports.ListNames = {}));
/**
* Maps from downstream client attribution name
* to list key sourced from upstream data provider.
*/
const phishingListNameKeyMap = {
[ListNames.Phishfort]: ListKeys.PhishfortHotlist,
[ListNames.MetaMask]: ListKeys.EthPhishingDetectConfig,
};
/**
* Maps from list key sourced from upstream data
* provider to downstream client attribution name.
*/
exports.phishingListKeyNameMap = {
[ListKeys.EthPhishingDetectConfig]: ListNames.MetaMask,
[ListKeys.PhishfortHotlist]: ListNames.Phishfort,
};
/**
* Controller that manages community-maintained lists of approved and unapproved website origins.

@@ -69,11 +113,13 @@ */

this.defaultState = {
listState: {
allowlist: config_json_1.default.whitelist,
blocklist: config_json_1.default.blacklist,
fuzzylist: config_json_1.default.fuzzylist,
tolerance: config_json_1.default.tolerance,
version: config_json_1.default.version,
name: 'MetaMask',
lastUpdated: 0,
},
phishingLists: [
{
allowlist: config_json_1.default.whitelist,
blocklist: config_json_1.default.blacklist,
fuzzylist: config_json_1.default.fuzzylist,
tolerance: config_json_1.default.tolerance,
version: config_json_1.default.version,
name: ListNames.MetaMask,
lastUpdated: 0,
},
],
whitelist: [],

@@ -90,12 +136,3 @@ hotlistLastFetched: 0,

updatePhishingDetector() {
this.detector = new detector_1.default([
{
allowlist: this.state.listState.allowlist,
blocklist: this.state.listState.blocklist,
fuzzylist: this.state.listState.fuzzylist,
tolerance: this.state.listState.tolerance,
name: `MetaMask`,
version: this.state.listState.version,
},
]);
this.detector = new detector_1.default(this.state.phishingLists);
}

@@ -253,9 +290,11 @@ /**

}
let stalelist;
let hotlistDiffs;
let stalelistResponse;
let hotlistDiffsResponse;
try {
[stalelist, hotlistDiffs] = yield Promise.all([
this.queryConfig(exports.METAMASK_STALELIST_URL),
this.queryConfig(exports.METAMASK_HOTLIST_DIFF_URL),
]);
stalelistResponse = yield this.queryConfig(exports.METAMASK_STALELIST_URL).then((d) => d);
// Fetching hotlist diffs relies on having a lastUpdated timestamp to do `GET /v1/diffsSince/:timestamp`,
// so it doesn't make sense to call if there is not a timestamp to begin with.
if ((stalelistResponse === null || stalelistResponse === void 0 ? void 0 : stalelistResponse.data) && stalelistResponse.data.lastUpdated > 0) {
hotlistDiffsResponse = yield this.queryConfig(`${exports.METAMASK_HOTLIST_DIFF_URL}/${stalelistResponse.data.lastUpdated}`);
}
}

@@ -271,9 +310,13 @@ finally {

}
if (!stalelist || !hotlistDiffs) {
if (!stalelistResponse || !hotlistDiffsResponse) {
return;
}
const _a = stalelistResponse.data, { phishfort_hotlist, eth_phishing_detect_config } = _a, partialState = __rest(_a, ["phishfort_hotlist", "eth_phishing_detect_config"]);
const phishfortListState = Object.assign(Object.assign(Object.assign({}, phishfort_hotlist), partialState), { fuzzylist: [], allowlist: [], name: exports.phishingListKeyNameMap.phishfort_hotlist });
const metamaskListState = Object.assign(Object.assign(Object.assign({}, eth_phishing_detect_config), partialState), { name: exports.phishingListKeyNameMap.eth_phishing_detect_config });
// Correctly shaping eth-phishing-detect state by applying hotlist diffs to the stalelist.
const newListState = (0, utils_1.applyDiffs)(stalelist, hotlistDiffs);
const newPhishfortListState = (0, utils_1.applyDiffs)(phishfortListState, hotlistDiffsResponse.data, ListKeys.PhishfortHotlist);
const newMetaMaskListState = (0, utils_1.applyDiffs)(metamaskListState, hotlistDiffsResponse.data, ListKeys.EthPhishingDetectConfig);
this.update({
listState: newListState,
phishingLists: [newMetaMaskListState, newPhishfortListState],
});

@@ -287,8 +330,9 @@ this.updatePhishingDetector();

}
let hotlistDiffs;
const lastDiffTimestamp = Math.max(...this.state.phishingLists.map(({ lastUpdated }) => lastUpdated));
let hotlistResponse;
try {
hotlistDiffs = yield this.queryConfig(exports.METAMASK_HOTLIST_DIFF_URL);
hotlistResponse = yield this.queryConfig(`${exports.METAMASK_HOTLIST_DIFF_URL}/${lastDiffTimestamp}`);
}
finally {
// Set `stalelistLastFetched` even for failed requests to prevent server from being overwhelmed with
// Set `hotlistLastFetched` even for failed requests to prevent server from being overwhelmed with
// traffic after a network disruption.

@@ -299,9 +343,9 @@ this.update({

}
if (!hotlistDiffs) {
if (!(hotlistResponse === null || hotlistResponse === void 0 ? void 0 : hotlistResponse.data)) {
return;
}
// Correctly shaping MetaMask config.
const newListState = (0, utils_1.applyDiffs)(this.state.listState, hotlistDiffs);
const hotlist = hotlistResponse.data;
const newPhishingLists = this.state.phishingLists.map((phishingList) => (0, utils_1.applyDiffs)(phishingList, hotlist, phishingListNameKeyMap[phishingList.name]));
this.update({
listState: newListState,
phishingLists: newPhishingLists,
});

@@ -308,0 +352,0 @@ this.updatePhishingDetector();

@@ -1,2 +0,2 @@

import { Hotlist, PhishingListState, PhishingStalelist } from './PhishingController';
import { Hotlist, ListKeys, PhishingListState } from './PhishingController';
/**

@@ -13,4 +13,6 @@ * Fetches current epoch time in seconds.

* @param hotlistDiffs - the diffs to apply to the listState if valid.
* @param listKey - the key associated with the input/output phishing list state.
* @returns the new list state
*/
export declare const applyDiffs: (listState: PhishingStalelist, hotlistDiffs: Hotlist) => PhishingListState;
export declare const applyDiffs: (listState: PhishingListState, hotlistDiffs: Hotlist, listKey: ListKeys) => PhishingListState;
//# sourceMappingURL=utils.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyDiffs = exports.fetchTimeNow = void 0;
const PhishingController_1 = require("./PhishingController");
/**

@@ -12,2 +13,15 @@ * Fetches current epoch time in seconds.

/**
* Split a string into two pieces, using the first period as the delimiter.
*
* @param stringToSplit - The string to split.
* @returns An array of length two containing the beginning and end of the string.
*/
const splitStringByPeriod = (stringToSplit) => {
const periodIndex = stringToSplit.indexOf('.');
return [
stringToSplit.slice(0, periodIndex),
stringToSplit.slice(periodIndex + 1),
];
};
/**
* Determines which diffs are applicable to the listState, then applies those diffs.

@@ -17,6 +31,15 @@ *

* @param hotlistDiffs - the diffs to apply to the listState if valid.
* @param listKey - the key associated with the input/output phishing list state.
* @returns the new list state
*/
const applyDiffs = (listState, hotlistDiffs) => {
const diffsToApply = hotlistDiffs.filter(({ timestamp }) => timestamp > listState.lastUpdated);
const applyDiffs = (listState, hotlistDiffs, listKey) => {
// filter to remove diffs that were added before the lastUpdate time.
// filter to remove diffs that aren't applicable to the specified list (by listKey).
const diffsToApply = hotlistDiffs.filter(({ timestamp, targetList }) => timestamp > listState.lastUpdated &&
splitStringByPeriod(targetList)[0] === listKey);
// the reason behind using latestDiffTimestamp as the lastUpdated time
// is so that we can benefit server-side from memoization due to end client's
// `GET /v1/diffSince/:timestamp` requests lining up with
// our periodic updates (which create diffs at specific timestamps).
let latestDiffTimestamp = listState.lastUpdated;
const listSets = {

@@ -27,11 +50,14 @@ allowlist: new Set(listState.allowlist),

};
for (const { isRemoval, targetList, url } of diffsToApply) {
for (const { isRemoval, targetList, url, timestamp } of diffsToApply) {
const targetListType = splitStringByPeriod(targetList)[1];
if (timestamp > latestDiffTimestamp) {
latestDiffTimestamp = timestamp;
}
if (isRemoval) {
listSets[targetList].delete(url);
listSets[targetListType].delete(url);
}
else {
listSets[targetList].add(url);
listSets[targetListType].add(url);
}
}
const now = (0, exports.fetchTimeNow)();
return {

@@ -42,5 +68,5 @@ allowlist: Array.from(listSets.allowlist),

version: listState.version,
name: 'MetaMask',
name: PhishingController_1.phishingListKeyNameMap[listKey],
tolerance: listState.tolerance,
lastUpdated: now,
lastUpdated: latestDiffTimestamp,
};

@@ -47,0 +73,0 @@ };

{
"name": "@metamask/phishing-controller",
"version": "3.0.0",
"version": "4.0.0",
"description": "Maintains a periodically updated list of approved and unapproved website origins",

@@ -33,3 +33,3 @@ "keywords": [

"@metamask/base-controller": "^2.0.0",
"@metamask/controller-utils": "^3.0.0",
"@metamask/controller-utils": "^3.1.0",
"@types/punycode": "^2.1.0",

@@ -36,0 +36,0 @@ "eth-phishing-detect": "^1.2.0",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc