Add detectPackage (#878)

* Add detectPackage

* Update packages/phishing/src/bundle.ts
This commit is contained in:
Jaco
2021-12-31 10:55:16 +01:00
committed by GitHub
parent 2d4df33c09
commit 6a4265621a
9 changed files with 182 additions and 134 deletions
+13
View File
@@ -1,5 +1,18 @@
# CHANGELOG
## 0.7.1 Dec 31, 2021
Contributed:
- Too many URLs to mention
Changes:
- Add `detectPackage` to check for duplicate instances
- Adjust consistency tests
- Split metadata into months
## 0.6.1 Feb 28, 2021
Contributed:
+1 -1
View File
@@ -10,7 +10,7 @@
"url": "https://github.com/polkadot-js/phishing.git"
},
"sideEffects": false,
"version": "0.6.598",
"version": "0.7.0",
"workspaces": [
"packages/*"
],
+5 -2
View File
@@ -12,9 +12,12 @@
"type": "git",
"url": "https://github.com/polkadot-js/phishing.git"
},
"sideEffects": false,
"sideEffects": [
"./detectPackage.js",
"./detectPackage.cjs"
],
"type": "module",
"version": "0.6.598",
"version": "0.7.0",
"main": "index.js",
"dependencies": {
"@babel/runtime": "^7.16.7",
+137
View File
@@ -0,0 +1,137 @@
// Copyright 2020-2021 @polkadot/phishing authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { AddressList, HostList } from './types';
import { u8aEq } from '@polkadot/util';
import { decodeAddress } from '@polkadot/util-crypto';
import { fetchWithTimeout } from './fetch';
export { packageInfo } from './packageInfo';
// Equivalent to https://raw.githubusercontent.com/polkadot-js/phishing/master/{address,all}.json
const ADDRESS_JSON = 'https://polkadot.js.org/phishing/address.json';
const ALL_JSON = 'https://polkadot.js.org/phishing/all.json';
// 45 minutes cache refresh
const CACHE_TIMEOUT = 45 * 60 * 1000;
let cacheAddrEnd = 0;
let cacheAddrList: AddressList | null = null;
let cacheAddrU8a: [string, Uint8Array[]][] | null = null;
let cacheHostEnd = 0;
let cacheHostList: HostList | null = null;
// gets the host-only part for a host
function extractHost (path: string): string {
return path
.replace(/https:\/\/|http:\/\/|wss:\/\/|ws:\/\//, '')
.split('/')[0];
}
/**
* Retrieve a list of known phishing addresses
*/
export async function retrieveAddrList (allowCached = true): Promise<AddressList> {
const now = Date.now();
if (allowCached && cacheAddrList && (now < cacheAddrEnd)) {
return cacheAddrList;
}
const response = await fetchWithTimeout(ADDRESS_JSON);
const list = (await response.json()) as AddressList;
cacheAddrEnd = now + CACHE_TIMEOUT;
cacheAddrList = list;
return list;
}
async function retrieveAddrU8a (allowCached = true): Promise<[string, Uint8Array[]][]> {
const now = Date.now();
if (allowCached && cacheAddrU8a && (now < cacheAddrEnd)) {
return cacheAddrU8a;
}
const all = await retrieveAddrList(allowCached);
cacheAddrU8a = Object
.entries(all)
.map(([key, addresses]): [string, Uint8Array[]] => [key, addresses.map((a) => decodeAddress(a))]);
return cacheAddrU8a;
}
/**
* Retrieve allow/deny from our list provider
*/
export async function retrieveHostList (allowCached = true): Promise<HostList> {
const now = Date.now();
if (allowCached && cacheHostList && (now < cacheHostEnd)) {
return cacheHostList;
}
const response = await fetchWithTimeout(ALL_JSON);
const list = (await response.json()) as HostList;
cacheHostEnd = now + CACHE_TIMEOUT;
cacheHostList = list;
return list;
}
/**
* Checks a host to see if it appears in the provided list
*/
export function checkHost (items: string[], host: string): boolean {
const hostParts = extractHost(host).split('.').reverse();
return items.some((item): boolean => {
const checkParts = item.split('.').reverse();
// first we need to ensure it has less or equal parts to our source
if (checkParts.length > hostParts.length) {
return false;
}
// ensure each section matches
return checkParts.every((part, index) => hostParts[index] === part);
});
}
/**
* Determines if a host is in our deny list. Returns a string containing the phishing site if host is a
* problematic one. Returns null if the address is not associated with phishing.
*/
export async function checkAddress (address: string | Uint8Array, allowCached = true): Promise<string | null> {
try {
const all = await retrieveAddrU8a(allowCached);
const u8a = decodeAddress(address);
const entry = all.find(([, all]) => all.some((a) => u8aEq(a, u8a))) || [null];
return entry[0];
} catch (error) {
console.error('Exception while checking address, assuming non-phishing', (error as Error).message);
return null;
}
}
/**
* Determines if a host is in our deny list. Returns true if host is a problematic one. Returns
* false if the host provided is not in our list of less-than-honest sites.
*/
export async function checkIfDenied (host: string, allowCached = true): Promise<boolean> {
try {
const { deny } = await retrieveHostList(allowCached);
return checkHost(deny, host);
} catch (error) {
console.error(`Exception while checking ${host}, assuming non-phishing`, (error as Error).message);
return false;
}
}
+6
View File
@@ -0,0 +1,6 @@
// Copyright 2020-2021 @polkadot/phishing authors & contributors
// SPDX-License-Identifier: Apache-2.0
declare const __dirname: string | undefined;
export default __dirname;
+6
View File
@@ -0,0 +1,6 @@
// Copyright 2020-2021 @polkadot/phishing authors & contributors
// SPDX-License-Identifier: Apache-2.0
module.exports = typeof __dirname === 'string'
? __dirname.replace('/cjs', '')
: undefined;
+3
View File
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
+9
View File
@@ -0,0 +1,9 @@
// Copyright 2020-2021 @polkadot/phishing authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { detectPackage } from '@polkadot/util';
import __dirname from './cjs/dirname';
import { packageInfo } from './packageInfo';
detectPackage(packageInfo, typeof __dirname !== 'undefined' && __dirname, []);
+2 -131
View File
@@ -1,135 +1,6 @@
// Copyright 2020-2021 @polkadot/phishing authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { AddressList, HostList } from './types';
import './detectPackage';
import { u8aEq } from '@polkadot/util';
import { decodeAddress } from '@polkadot/util-crypto';
import { fetchWithTimeout } from './fetch';
// Equivalent to https://raw.githubusercontent.com/polkadot-js/phishing/master/{address,all}.json
const ADDRESS_JSON = 'https://polkadot.js.org/phishing/address.json';
const ALL_JSON = 'https://polkadot.js.org/phishing/all.json';
// 1 hour cache refresh
const CACHE_TIMEOUT = 45 * 60 * 1000;
let cacheAddrEnd = 0;
let cacheAddrList: AddressList | null = null;
let cacheAddrU8a: [string, Uint8Array[]][] | null = null;
let cacheHostEnd = 0;
let cacheHostList: HostList | null = null;
// gets the host-only part for a host
function extractHost (path: string): string {
return path
.replace(/https:\/\/|http:\/\/|wss:\/\/|ws:\/\//, '')
.split('/')[0];
}
/**
* Retrieve a list of known phishing addresses
*/
export async function retrieveAddrList (allowCached = true): Promise<AddressList> {
const now = Date.now();
if (allowCached && cacheAddrList && (now < cacheAddrEnd)) {
return cacheAddrList;
}
const response = await fetchWithTimeout(ADDRESS_JSON);
const list = (await response.json()) as AddressList;
cacheAddrEnd = now + CACHE_TIMEOUT;
cacheAddrList = list;
return list;
}
async function retrieveAddrU8a (allowCached = true): Promise<[string, Uint8Array[]][]> {
const now = Date.now();
if (allowCached && cacheAddrU8a && (now < cacheAddrEnd)) {
return cacheAddrU8a;
}
const all = await retrieveAddrList(allowCached);
cacheAddrU8a = Object
.entries(all)
.map(([key, addresses]): [string, Uint8Array[]] => [key, addresses.map((a) => decodeAddress(a))]);
return cacheAddrU8a;
}
/**
* Retrieve allow/deny from our list provider
*/
export async function retrieveHostList (allowCached = true): Promise<HostList> {
const now = Date.now();
if (allowCached && cacheHostList && (now < cacheHostEnd)) {
return cacheHostList;
}
const response = await fetchWithTimeout(ALL_JSON);
const list = (await response.json()) as HostList;
cacheHostEnd = now + CACHE_TIMEOUT;
cacheHostList = list;
return list;
}
/**
* Checks a host to see if it appears in the provided list
*/
export function checkHost (items: string[], host: string): boolean {
const hostParts = extractHost(host).split('.').reverse();
return items.some((item): boolean => {
const checkParts = item.split('.').reverse();
// first we need to ensure it has less or equal parts to our source
if (checkParts.length > hostParts.length) {
return false;
}
// ensure each section matches
return checkParts.every((part, index) => hostParts[index] === part);
});
}
/**
* Determines if a host is in our deny list. Returns a string containing the phishing site if host is a
* problematic one. Returns null if the address is not associated with phishing.
*/
export async function checkAddress (address: string | Uint8Array, allowCached = true): Promise<string | null> {
try {
const all = await retrieveAddrU8a(allowCached);
const u8a = decodeAddress(address);
const entry = all.find(([, all]) => all.some((a) => u8aEq(a, u8a))) || [null];
return entry[0];
} catch (error) {
console.error('Exception while checking address, assuming non-phishing', (error as Error).message);
return null;
}
}
/**
* Determines if a host is in our deny list. Returns true if host is a problematic one. Returns
* false if the host provided is not in our list of less-than-honest sites.
*/
export async function checkIfDenied (host: string, allowCached = true): Promise<boolean> {
try {
const { deny } = await retrieveHostList(allowCached);
return checkHost(deny, host);
} catch (error) {
console.error(`Exception while checking ${host}, assuming non-phishing`, (error as Error).message);
return false;
}
}
export * from './bundle';