fpscanner 0.2.0 → 0.9.2
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/README.md +639 -55
- package/bin/cli.js +216 -0
- package/dist/crypto-helpers.d.ts +19 -0
- package/dist/crypto-helpers.d.ts.map +1 -0
- package/dist/detections/hasCDP.d.ts +3 -0
- package/dist/detections/hasCDP.d.ts.map +1 -0
- package/dist/detections/hasContextMismatch.d.ts +3 -0
- package/dist/detections/hasContextMismatch.d.ts.map +1 -0
- package/dist/detections/hasHeadlessChromeScreenResolution.d.ts +3 -0
- package/dist/detections/hasHeadlessChromeScreenResolution.d.ts.map +1 -0
- package/dist/detections/hasHighCPUCount.d.ts +3 -0
- package/dist/detections/hasHighCPUCount.d.ts.map +1 -0
- package/dist/detections/hasImpossibleDeviceMemory.d.ts +3 -0
- package/dist/detections/hasImpossibleDeviceMemory.d.ts.map +1 -0
- package/dist/detections/hasMismatchPlatformIframe.d.ts +3 -0
- package/dist/detections/hasMismatchPlatformIframe.d.ts.map +1 -0
- package/dist/detections/hasMismatchPlatformWorker.d.ts +3 -0
- package/dist/detections/hasMismatchPlatformWorker.d.ts.map +1 -0
- package/dist/detections/hasMismatchWebGLInWorker.d.ts +3 -0
- package/dist/detections/hasMismatchWebGLInWorker.d.ts.map +1 -0
- package/dist/detections/hasMissingChromeObject.d.ts +3 -0
- package/dist/detections/hasMissingChromeObject.d.ts.map +1 -0
- package/dist/detections/hasPlaywright.d.ts +3 -0
- package/dist/detections/hasPlaywright.d.ts.map +1 -0
- package/dist/detections/hasSeleniumProperty.d.ts +3 -0
- package/dist/detections/hasSeleniumProperty.d.ts.map +1 -0
- package/dist/detections/hasSwiftshaderRenderer.d.ts +3 -0
- package/dist/detections/hasSwiftshaderRenderer.d.ts.map +1 -0
- package/dist/detections/hasUTCTimezone.d.ts +3 -0
- package/dist/detections/hasUTCTimezone.d.ts.map +1 -0
- package/dist/detections/hasWebdriver.d.ts +3 -0
- package/dist/detections/hasWebdriver.d.ts.map +1 -0
- package/dist/detections/hasWebdriverIframe.d.ts +3 -0
- package/dist/detections/hasWebdriverIframe.d.ts.map +1 -0
- package/dist/detections/hasWebdriverWorker.d.ts +3 -0
- package/dist/detections/hasWebdriverWorker.d.ts.map +1 -0
- package/dist/detections/hasWebdriverWritable.d.ts +3 -0
- package/dist/detections/hasWebdriverWritable.d.ts.map +1 -0
- package/dist/fpScanner.cjs.js +31 -0
- package/dist/fpScanner.es.js +1066 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/signals/browserExtensions.d.ts +5 -0
- package/dist/signals/browserExtensions.d.ts.map +1 -0
- package/dist/signals/browserFeatures.d.ts +14 -0
- package/dist/signals/browserFeatures.d.ts.map +1 -0
- package/dist/signals/canvas.d.ts +6 -0
- package/dist/signals/canvas.d.ts.map +1 -0
- package/dist/signals/cdp.d.ts +2 -0
- package/dist/signals/cdp.d.ts.map +1 -0
- package/dist/signals/cpuCount.d.ts +2 -0
- package/dist/signals/cpuCount.d.ts.map +1 -0
- package/dist/signals/etsl.d.ts +2 -0
- package/dist/signals/etsl.d.ts.map +1 -0
- package/dist/signals/highEntropyValues.d.ts +11 -0
- package/dist/signals/highEntropyValues.d.ts.map +1 -0
- package/dist/signals/iframe.d.ts +9 -0
- package/dist/signals/iframe.d.ts.map +1 -0
- package/dist/signals/internationalization.d.ts +5 -0
- package/dist/signals/internationalization.d.ts.map +1 -0
- package/dist/signals/languages.d.ts +5 -0
- package/dist/signals/languages.d.ts.map +1 -0
- package/dist/signals/maths.d.ts +2 -0
- package/dist/signals/maths.d.ts.map +1 -0
- package/dist/signals/mediaCodecs.d.ts +11 -0
- package/dist/signals/mediaCodecs.d.ts.map +1 -0
- package/dist/signals/mediaQueries.d.ts +13 -0
- package/dist/signals/mediaQueries.d.ts.map +1 -0
- package/dist/signals/memory.d.ts +2 -0
- package/dist/signals/memory.d.ts.map +1 -0
- package/dist/signals/multimediaDevices.d.ts +2 -0
- package/dist/signals/multimediaDevices.d.ts.map +1 -0
- package/dist/signals/navigatorPropertyDescriptors.d.ts +2 -0
- package/dist/signals/navigatorPropertyDescriptors.d.ts.map +1 -0
- package/dist/signals/nonce.d.ts +2 -0
- package/dist/signals/nonce.d.ts.map +1 -0
- package/dist/signals/platform.d.ts +2 -0
- package/dist/signals/platform.d.ts.map +1 -0
- package/dist/signals/playwright.d.ts +2 -0
- package/dist/signals/playwright.d.ts.map +1 -0
- package/dist/signals/plugins.d.ts +9 -0
- package/dist/signals/plugins.d.ts.map +1 -0
- package/dist/signals/screenResolution.d.ts +12 -0
- package/dist/signals/screenResolution.d.ts.map +1 -0
- package/dist/signals/seleniumProperties.d.ts +2 -0
- package/dist/signals/seleniumProperties.d.ts.map +1 -0
- package/dist/signals/time.d.ts +2 -0
- package/dist/signals/time.d.ts.map +1 -0
- package/dist/signals/toSourceError.d.ts +5 -0
- package/dist/signals/toSourceError.d.ts.map +1 -0
- package/dist/signals/url.d.ts +2 -0
- package/dist/signals/url.d.ts.map +1 -0
- package/dist/signals/userAgent.d.ts +2 -0
- package/dist/signals/userAgent.d.ts.map +1 -0
- package/dist/signals/utils.d.ts +11 -0
- package/dist/signals/utils.d.ts.map +1 -0
- package/dist/signals/webGL.d.ts +5 -0
- package/dist/signals/webGL.d.ts.map +1 -0
- package/dist/signals/webdriver.d.ts +2 -0
- package/dist/signals/webdriver.d.ts.map +1 -0
- package/dist/signals/webdriverWritable.d.ts +2 -0
- package/dist/signals/webdriverWritable.d.ts.map +1 -0
- package/dist/signals/webgpu.d.ts +7 -0
- package/dist/signals/webgpu.d.ts.map +1 -0
- package/dist/signals/worker.d.ts +2 -0
- package/dist/signals/worker.d.ts.map +1 -0
- package/dist/types.d.ts +207 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +58 -15
- package/scripts/build-custom.js +246 -0
- package/src/crypto-helpers.ts +50 -0
- package/src/detections/hasCDP.ts +5 -0
- package/src/detections/hasContextMismatch.ts +19 -0
- package/src/detections/hasHeadlessChromeScreenResolution.ts +10 -0
- package/src/detections/hasHighCPUCount.ts +9 -0
- package/src/detections/hasImpossibleDeviceMemory.ts +9 -0
- package/src/detections/hasMismatchPlatformIframe.ts +10 -0
- package/src/detections/hasMismatchPlatformWorker.ts +10 -0
- package/src/detections/hasMismatchWebGLInWorker.ts +13 -0
- package/src/detections/hasMissingChromeObject.ts +6 -0
- package/src/detections/hasPlaywright.ts +5 -0
- package/src/detections/hasSeleniumProperty.ts +5 -0
- package/src/detections/hasSwiftshaderRenderer.ts +5 -0
- package/src/detections/hasUTCTimezone.ts +5 -0
- package/src/detections/hasWebdriver.ts +5 -0
- package/src/detections/hasWebdriverIframe.ts +5 -0
- package/src/detections/hasWebdriverWorker.ts +5 -0
- package/src/detections/hasWebdriverWritable.ts +5 -0
- package/src/globals.d.ts +10 -0
- package/src/index.ts +644 -0
- package/src/signals/browserExtensions.ts +57 -0
- package/src/signals/browserFeatures.ts +24 -0
- package/src/signals/canvas.ts +84 -0
- package/src/signals/cdp.ts +18 -0
- package/src/signals/cpuCount.ts +5 -0
- package/src/signals/etsl.ts +3 -0
- package/src/signals/highEntropyValues.ts +48 -0
- package/src/signals/iframe.ts +34 -0
- package/src/signals/internationalization.ts +24 -0
- package/src/signals/languages.ts +6 -0
- package/src/signals/maths.ts +30 -0
- package/src/signals/mediaCodecs.ts +120 -0
- package/src/signals/mediaQueries.ts +85 -0
- package/src/signals/memory.ts +5 -0
- package/src/signals/multimediaDevices.ts +34 -0
- package/src/signals/navigatorPropertyDescriptors.ts +17 -0
- package/src/signals/nonce.ts +3 -0
- package/src/signals/platform.ts +3 -0
- package/src/signals/playwright.ts +3 -0
- package/src/signals/plugins.ts +70 -0
- package/src/signals/screenResolution.ts +15 -0
- package/src/signals/seleniumProperties.ts +40 -0
- package/src/signals/time.ts +3 -0
- package/src/signals/toSourceError.ts +27 -0
- package/src/signals/url.ts +3 -0
- package/src/signals/userAgent.ts +3 -0
- package/src/signals/utils.ts +29 -0
- package/src/signals/webGL.ts +28 -0
- package/src/signals/webdriver.ts +3 -0
- package/src/signals/webdriverWritable.ts +15 -0
- package/src/signals/webgpu.ts +28 -0
- package/src/signals/worker.ts +77 -0
- package/src/types.ts +237 -0
- package/.babelrc +0 -3
- package/.travis.yml +0 -17
- package/src/fpScanner.js +0 -222
- package/test/test.html +0 -11
- package/test/test.js +0 -116
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { SignalValue } from "../types";
|
|
2
|
+
import { INIT, NA, hashCode, ERROR, setObjectValues} from "./utils";
|
|
3
|
+
|
|
4
|
+
function isValidPluginArray() {
|
|
5
|
+
if (!navigator.plugins) return false;
|
|
6
|
+
const str = typeof navigator.plugins.toString === "function"
|
|
7
|
+
? navigator.plugins.toString()
|
|
8
|
+
: navigator.plugins.constructor && typeof navigator.plugins.constructor.toString === "function"
|
|
9
|
+
? navigator.plugins.constructor.toString()
|
|
10
|
+
: typeof navigator.plugins;
|
|
11
|
+
return str === "[object PluginArray]" ||
|
|
12
|
+
str === "[object MSPluginsCollection]" ||
|
|
13
|
+
str === "[object HTMLPluginsCollection]";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function getPluginNamesHash() {
|
|
17
|
+
if (!navigator.plugins) return NA;
|
|
18
|
+
|
|
19
|
+
const pluginNames = [];
|
|
20
|
+
for (let i = 0; i < navigator.plugins.length; i++) {
|
|
21
|
+
pluginNames.push(navigator.plugins[i].name);
|
|
22
|
+
}
|
|
23
|
+
return hashCode(pluginNames.join(","));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
function getPluginCount() {
|
|
28
|
+
if (!navigator.plugins) return NA;
|
|
29
|
+
return navigator.plugins.length;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getPluginConsistency1() {
|
|
33
|
+
if (!navigator.plugins) return NA;
|
|
34
|
+
try {
|
|
35
|
+
return navigator.plugins[0] === navigator.plugins[0][0].enabledPlugin;
|
|
36
|
+
} catch (e) {
|
|
37
|
+
return ERROR;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getPluginOverflow() {
|
|
42
|
+
if (!navigator.plugins) return NA;
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
return navigator.plugins.item(4294967296) !== navigator.plugins[0];
|
|
46
|
+
} catch (e) {
|
|
47
|
+
return ERROR;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function plugins() {
|
|
52
|
+
const pluginsData = {
|
|
53
|
+
isValidPluginArray: INIT as SignalValue<boolean>,
|
|
54
|
+
pluginCount: INIT as SignalValue<number>,
|
|
55
|
+
pluginNamesHash: INIT as SignalValue<string>,
|
|
56
|
+
pluginConsistency1: INIT as SignalValue<boolean>,
|
|
57
|
+
pluginOverflow: INIT as SignalValue<boolean>,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
pluginsData.isValidPluginArray = isValidPluginArray();
|
|
62
|
+
pluginsData.pluginCount = getPluginCount();
|
|
63
|
+
pluginsData.pluginNamesHash = getPluginNamesHash();
|
|
64
|
+
pluginsData.pluginConsistency1 = getPluginConsistency1();
|
|
65
|
+
pluginsData.pluginOverflow = getPluginOverflow();
|
|
66
|
+
} catch (e) {
|
|
67
|
+
setObjectValues(pluginsData, ERROR);
|
|
68
|
+
}
|
|
69
|
+
return pluginsData;
|
|
70
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NA } from './utils';
|
|
2
|
+
|
|
3
|
+
export function screenResolution() {
|
|
4
|
+
return {
|
|
5
|
+
width: window.screen.width,
|
|
6
|
+
height: window.screen.height,
|
|
7
|
+
pixelDepth: window.screen.pixelDepth,
|
|
8
|
+
colorDepth: window.screen.colorDepth,
|
|
9
|
+
availableWidth: window.screen.availWidth,
|
|
10
|
+
availableHeight: window.screen.availHeight,
|
|
11
|
+
innerWidth: window.innerWidth,
|
|
12
|
+
innerHeight: window.innerHeight,
|
|
13
|
+
hasMultipleDisplays: typeof (screen as any).isExtended !== 'undefined' ? (screen as any).isExtended : NA,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export function hasSeleniumProperties() {
|
|
2
|
+
const seleniumProps = [
|
|
3
|
+
"__driver_evaluate",
|
|
4
|
+
"__webdriver_evaluate",
|
|
5
|
+
"__selenium_evaluate",
|
|
6
|
+
"__fxdriver_evaluate",
|
|
7
|
+
"__driver_unwrapped",
|
|
8
|
+
"__webdriver_unwrapped",
|
|
9
|
+
"__selenium_unwrapped",
|
|
10
|
+
"__fxdriver_unwrapped",
|
|
11
|
+
"_Selenium_IDE_Recorder",
|
|
12
|
+
"_selenium",
|
|
13
|
+
"calledSelenium",
|
|
14
|
+
"$cdc_asdjflasutopfhvcZLmcfl_",
|
|
15
|
+
"$chrome_asyncScriptInfo",
|
|
16
|
+
"__$webdriverAsyncExecutor",
|
|
17
|
+
"webdriver",
|
|
18
|
+
"__webdriverFunc",
|
|
19
|
+
"domAutomation",
|
|
20
|
+
"domAutomationController",
|
|
21
|
+
"__lastWatirAlert",
|
|
22
|
+
"__lastWatirConfirm",
|
|
23
|
+
"__lastWatirPrompt",
|
|
24
|
+
"__webdriver_script_fn",
|
|
25
|
+
"_WEBDRIVER_ELEM_CACHE"
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
let hasSeleniumProperty = false;
|
|
29
|
+
|
|
30
|
+
for (let i = 0; i < seleniumProps.length; i++) {
|
|
31
|
+
if (seleniumProps[i] in window) {
|
|
32
|
+
hasSeleniumProperty = true;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
hasSeleniumProperty = hasSeleniumProperty || !!(document as any).__webdriver_script_fn || !!(window as any).domAutomation || !!(window as any).domAutomationController
|
|
38
|
+
|
|
39
|
+
return hasSeleniumProperty;
|
|
40
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { INIT } from './utils';
|
|
2
|
+
|
|
3
|
+
export function toSourceError() {
|
|
4
|
+
const toSourceErrorData = {
|
|
5
|
+
toSourceError: INIT,
|
|
6
|
+
hasToSource: false,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
(null as any).usdfsh;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
toSourceErrorData.toSourceError = (e as Error).toString();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
throw "xyz";
|
|
17
|
+
} catch (e: any) {
|
|
18
|
+
try {
|
|
19
|
+
e.toSource();
|
|
20
|
+
toSourceErrorData.hasToSource = true;
|
|
21
|
+
} catch (e2) {
|
|
22
|
+
toSourceErrorData.hasToSource = false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return toSourceErrorData;
|
|
27
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const ERROR = 'ERROR';
|
|
2
|
+
export const INIT = 'INIT';
|
|
3
|
+
export const NA = 'NA';
|
|
4
|
+
export const SKIPPED = 'SKIPPED';
|
|
5
|
+
export const HIGH = 'high'
|
|
6
|
+
export const LOW = 'low'
|
|
7
|
+
export const MEDIUM = 'medium'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
export function hashCode(str: string) {
|
|
11
|
+
let hash = 0;
|
|
12
|
+
for (let i = 0, len = str.length; i < len; i++) {
|
|
13
|
+
let chr = str.charCodeAt(i);
|
|
14
|
+
hash = (hash << 5) - hash + chr;
|
|
15
|
+
hash |= 0;
|
|
16
|
+
}
|
|
17
|
+
return hash.toString(16).padStart(8, "0");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function setObjectValues(object: any, value: any) {
|
|
21
|
+
for (const key in object) {
|
|
22
|
+
object[key] = value;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
export function isFirefox() {
|
|
28
|
+
return (navigator as any).buildID === "20181001000000";
|
|
29
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ERROR, INIT, NA, isFirefox, setObjectValues } from './utils';
|
|
2
|
+
|
|
3
|
+
export function webGL() {
|
|
4
|
+
const webGLData = {
|
|
5
|
+
vendor: INIT,
|
|
6
|
+
renderer: INIT,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
if (isFirefox()) {
|
|
10
|
+
setObjectValues(webGLData, NA);
|
|
11
|
+
return webGLData;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
var canvas = document.createElement('canvas');
|
|
16
|
+
var ctx = (canvas.getContext("webgl") || canvas.getContext("experimental-webgl")) as any;
|
|
17
|
+
if (ctx.getSupportedExtensions().indexOf("WEBGL_debug_renderer_info") >= 0) {
|
|
18
|
+
webGLData.vendor = ctx.getParameter(ctx.getExtension('WEBGL_debug_renderer_info').UNMASKED_VENDOR_WEBGL);
|
|
19
|
+
webGLData.renderer = ctx.getParameter(ctx.getExtension('WEBGL_debug_renderer_info').UNMASKED_RENDERER_WEBGL);
|
|
20
|
+
} else {
|
|
21
|
+
setObjectValues(webGLData, NA);
|
|
22
|
+
}
|
|
23
|
+
} catch (e) {
|
|
24
|
+
setObjectValues(webGLData, ERROR);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return webGLData;
|
|
28
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function webdriverWritable() {
|
|
2
|
+
try {
|
|
3
|
+
const prop = "webdriver";
|
|
4
|
+
const navigator = window.navigator as any;
|
|
5
|
+
if (!navigator[prop] && !navigator.hasOwnProperty(prop)) {
|
|
6
|
+
navigator[prop] = 1;
|
|
7
|
+
const writable = navigator[prop] === 1;
|
|
8
|
+
delete navigator[prop];
|
|
9
|
+
return writable;
|
|
10
|
+
}
|
|
11
|
+
return true;
|
|
12
|
+
} catch (e) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ERROR, INIT, NA, setObjectValues } from "./utils";
|
|
2
|
+
|
|
3
|
+
export async function webgpu() {
|
|
4
|
+
const webGPUData = {
|
|
5
|
+
vendor: INIT,
|
|
6
|
+
architecture: INIT,
|
|
7
|
+
device: INIT,
|
|
8
|
+
description: INIT,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
if ('gpu' in navigator) {
|
|
12
|
+
try {
|
|
13
|
+
const adapter = await (navigator as any).gpu.requestAdapter();
|
|
14
|
+
if (adapter) {
|
|
15
|
+
webGPUData.vendor = adapter.info.vendor;
|
|
16
|
+
webGPUData.architecture = adapter.info.architecture;
|
|
17
|
+
webGPUData.device = adapter.info.device;
|
|
18
|
+
webGPUData.description = adapter.info.description;
|
|
19
|
+
}
|
|
20
|
+
} catch (e) {
|
|
21
|
+
setObjectValues(webGPUData, ERROR);
|
|
22
|
+
}
|
|
23
|
+
} else {
|
|
24
|
+
setObjectValues(webGPUData, NA);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return webGPUData;
|
|
28
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ERROR, INIT, setObjectValues } from './utils';
|
|
2
|
+
|
|
3
|
+
export async function worker() {
|
|
4
|
+
return new Promise((resolve) => {
|
|
5
|
+
const workerData = {
|
|
6
|
+
vendor: INIT,
|
|
7
|
+
renderer: INIT,
|
|
8
|
+
userAgent: INIT,
|
|
9
|
+
language: INIT,
|
|
10
|
+
platform: INIT,
|
|
11
|
+
memory: INIT,
|
|
12
|
+
cpuCount: INIT,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const workerCode = `try {
|
|
17
|
+
var fingerprintWorker = {};
|
|
18
|
+
|
|
19
|
+
fingerprintWorker.userAgent = navigator.userAgent;
|
|
20
|
+
fingerprintWorker.language = navigator.language;
|
|
21
|
+
fingerprintWorker.cpuCount = navigator.hardwareConcurrency;
|
|
22
|
+
fingerprintWorker.platform = navigator.platform;
|
|
23
|
+
fingerprintWorker.memory = navigator.deviceMemory;
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
var canvas = new OffscreenCanvas(1, 1);
|
|
27
|
+
fingerprintWorker.vendor = 'INIT';
|
|
28
|
+
fingerprintWorker.renderer = 'INIT';
|
|
29
|
+
var gl = canvas.getContext('webgl');
|
|
30
|
+
try {
|
|
31
|
+
if (gl) {
|
|
32
|
+
var glExt = gl.getExtension('WEBGL_debug_renderer_info');
|
|
33
|
+
fingerprintWorker.vendor = gl.getParameter(glExt.UNMASKED_VENDOR_WEBGL);
|
|
34
|
+
fingerprintWorker.renderer = gl.getParameter(glExt.UNMASKED_RENDERER_WEBGL);
|
|
35
|
+
} else {
|
|
36
|
+
fingerprintWorker.vendor = 'NA';
|
|
37
|
+
fingerprintWorker.renderer = 'NA';
|
|
38
|
+
}
|
|
39
|
+
} catch (_) {
|
|
40
|
+
fingerprintWorker.vendor = 'ERROR';
|
|
41
|
+
fingerprintWorker.renderer = 'ERROR';
|
|
42
|
+
}
|
|
43
|
+
self.postMessage(fingerprintWorker);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
self.postMessage(fingerprintWorker);
|
|
46
|
+
}`
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
const blob = new Blob([workerCode], { type: 'application/javascript' });
|
|
50
|
+
const workerUrl = URL.createObjectURL(blob);
|
|
51
|
+
const worker = new Worker(workerUrl);
|
|
52
|
+
|
|
53
|
+
worker.onmessage = function (e) {
|
|
54
|
+
try {
|
|
55
|
+
workerData.vendor = e.data.vendor;
|
|
56
|
+
workerData.renderer = e.data.renderer;
|
|
57
|
+
workerData.userAgent = e.data.userAgent;
|
|
58
|
+
workerData.language = e.data.language;
|
|
59
|
+
workerData.platform = e.data.platform;
|
|
60
|
+
workerData.memory = e.data.memory;
|
|
61
|
+
workerData.cpuCount = e.data.cpuCount;
|
|
62
|
+
|
|
63
|
+
return resolve(workerData);
|
|
64
|
+
} catch (_) {
|
|
65
|
+
setObjectValues(workerData, ERROR);
|
|
66
|
+
return resolve(workerData);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
} catch (e) {
|
|
70
|
+
setObjectValues(workerData, ERROR);
|
|
71
|
+
|
|
72
|
+
return resolve(workerData);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { ERROR, INIT, NA, SKIPPED } from './signals/utils';
|
|
2
|
+
|
|
3
|
+
export type SignalValue<T> = T | typeof ERROR | typeof INIT | typeof NA | typeof SKIPPED;
|
|
4
|
+
|
|
5
|
+
export interface WebGLSignal {
|
|
6
|
+
vendor: SignalValue<string>;
|
|
7
|
+
renderer: SignalValue<string>;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface InternationalizationSignal {
|
|
11
|
+
timezone: SignalValue<string>;
|
|
12
|
+
localeLanguage: SignalValue<string>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ScreenResolutionSignal {
|
|
16
|
+
width: SignalValue<number>;
|
|
17
|
+
height: SignalValue<number>;
|
|
18
|
+
pixelDepth: SignalValue<number>;
|
|
19
|
+
colorDepth: SignalValue<number>;
|
|
20
|
+
availableWidth: SignalValue<number>;
|
|
21
|
+
availableHeight: SignalValue<number>;
|
|
22
|
+
innerWidth: SignalValue<number>;
|
|
23
|
+
innerHeight: SignalValue<number>;
|
|
24
|
+
hasMultipleDisplays: SignalValue<boolean>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface LanguagesSignal {
|
|
28
|
+
languages: SignalValue<string[]>;
|
|
29
|
+
language: SignalValue<string>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface WebGPUSignal {
|
|
33
|
+
vendor: SignalValue<string>;
|
|
34
|
+
architecture: SignalValue<string>;
|
|
35
|
+
device: SignalValue<string>;
|
|
36
|
+
description: SignalValue<string>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface IframeSignal {
|
|
40
|
+
webdriver: SignalValue<boolean>;
|
|
41
|
+
userAgent: SignalValue<string>;
|
|
42
|
+
platform: SignalValue<string>;
|
|
43
|
+
memory: SignalValue<number>;
|
|
44
|
+
cpuCount: SignalValue<number>;
|
|
45
|
+
language: SignalValue<string>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface WebWorkerSignal {
|
|
49
|
+
webdriver: SignalValue<boolean>;
|
|
50
|
+
userAgent: SignalValue<string>;
|
|
51
|
+
platform: SignalValue<string>;
|
|
52
|
+
memory: SignalValue<number>;
|
|
53
|
+
cpuCount: SignalValue<number>;
|
|
54
|
+
language: SignalValue<string>;
|
|
55
|
+
vendor: SignalValue<string>;
|
|
56
|
+
renderer: SignalValue<string>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface BrowserExtensionsSignal {
|
|
60
|
+
bitmask: SignalValue<string>;
|
|
61
|
+
extensions: SignalValue<string[]>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface BrowserFeaturesSignal {
|
|
65
|
+
bitmask: SignalValue<string>;
|
|
66
|
+
chrome: SignalValue<boolean>;
|
|
67
|
+
brave: SignalValue<boolean>;
|
|
68
|
+
applePaySupport: SignalValue<boolean>;
|
|
69
|
+
opera: SignalValue<boolean>;
|
|
70
|
+
serial: SignalValue<boolean>;
|
|
71
|
+
attachShadow: SignalValue<boolean>;
|
|
72
|
+
caches: SignalValue<boolean>;
|
|
73
|
+
webAssembly: SignalValue<boolean>;
|
|
74
|
+
buffer: SignalValue<boolean>;
|
|
75
|
+
showModalDialog: SignalValue<boolean>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface MediaQueriesSignal {
|
|
79
|
+
prefersColorScheme: SignalValue<string | null>;
|
|
80
|
+
prefersReducedMotion: SignalValue<boolean>;
|
|
81
|
+
prefersReducedTransparency: SignalValue<boolean>;
|
|
82
|
+
colorGamut: SignalValue<string | null>;
|
|
83
|
+
pointer: SignalValue<string | null>;
|
|
84
|
+
anyPointer: SignalValue<string | null>;
|
|
85
|
+
hover: SignalValue<boolean>;
|
|
86
|
+
anyHover: SignalValue<boolean>;
|
|
87
|
+
colorDepth: SignalValue<number>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface ToSourceErrorSignal {
|
|
91
|
+
toSourceError: SignalValue<string>;
|
|
92
|
+
hasToSource: SignalValue<boolean>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface CanvasSignal {
|
|
96
|
+
hasModifiedCanvas: SignalValue<boolean>;
|
|
97
|
+
canvasFingerprint: SignalValue<string>;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface HighEntropyValuesSignal {
|
|
101
|
+
architecture: SignalValue<string>;
|
|
102
|
+
bitness: SignalValue<string>;
|
|
103
|
+
brands: SignalValue<string[]>;
|
|
104
|
+
mobile: SignalValue<boolean>;
|
|
105
|
+
model: SignalValue<string>;
|
|
106
|
+
platform: SignalValue<string>;
|
|
107
|
+
platformVersion: SignalValue<string>;
|
|
108
|
+
uaFullVersion: SignalValue<string>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface PluginsSignal {
|
|
112
|
+
isValidPluginArray: SignalValue<boolean>;
|
|
113
|
+
pluginCount: SignalValue<number>;
|
|
114
|
+
pluginNamesHash: SignalValue<string>;
|
|
115
|
+
pluginConsistency1: SignalValue<boolean>;
|
|
116
|
+
pluginOverflow: SignalValue<boolean>;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface MultimediaDevicesSignal {
|
|
120
|
+
speakers: SignalValue<number>;
|
|
121
|
+
microphones: SignalValue<number>;
|
|
122
|
+
webcams: SignalValue<number>;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface MediaCodecsSignal {
|
|
126
|
+
audioCanPlayTypeHash: SignalValue<string>;
|
|
127
|
+
videoCanPlayTypeHash: SignalValue<string>;
|
|
128
|
+
audioMediaSourceHash: SignalValue<string>;
|
|
129
|
+
videoMediaSourceHash: SignalValue<string>;
|
|
130
|
+
rtcAudioCapabilitiesHash: SignalValue<string>;
|
|
131
|
+
rtcVideoCapabilitiesHash: SignalValue<string>;
|
|
132
|
+
hasMediaSource: SignalValue<boolean>;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Grouped signal interfaces
|
|
136
|
+
export interface AutomationSignals {
|
|
137
|
+
webdriver: SignalValue<boolean>;
|
|
138
|
+
webdriverWritable: SignalValue<boolean>;
|
|
139
|
+
selenium: SignalValue<boolean>;
|
|
140
|
+
cdp: SignalValue<boolean>;
|
|
141
|
+
playwright: SignalValue<boolean>;
|
|
142
|
+
navigatorPropertyDescriptors: SignalValue<string>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface DeviceSignals {
|
|
146
|
+
cpuCount: SignalValue<number>;
|
|
147
|
+
memory: SignalValue<number>;
|
|
148
|
+
platform: SignalValue<string>;
|
|
149
|
+
screenResolution: ScreenResolutionSignal;
|
|
150
|
+
multimediaDevices: MultimediaDevicesSignal;
|
|
151
|
+
mediaQueries: MediaQueriesSignal;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export interface BrowserSignals {
|
|
155
|
+
userAgent: SignalValue<string>;
|
|
156
|
+
features: BrowserFeaturesSignal;
|
|
157
|
+
plugins: PluginsSignal;
|
|
158
|
+
extensions: BrowserExtensionsSignal;
|
|
159
|
+
highEntropyValues: HighEntropyValuesSignal;
|
|
160
|
+
etsl: SignalValue<number>;
|
|
161
|
+
maths: SignalValue<string>;
|
|
162
|
+
toSourceError: ToSourceErrorSignal;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export interface GraphicsSignals {
|
|
166
|
+
webGL: WebGLSignal;
|
|
167
|
+
webgpu: WebGPUSignal;
|
|
168
|
+
canvas: CanvasSignal;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export interface LocaleSignals {
|
|
172
|
+
internationalization: InternationalizationSignal;
|
|
173
|
+
languages: LanguagesSignal;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface ContextsSignals {
|
|
177
|
+
iframe: IframeSignal;
|
|
178
|
+
webWorker: WebWorkerSignal;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface FingerprintSignals {
|
|
182
|
+
automation: AutomationSignals;
|
|
183
|
+
device: DeviceSignals;
|
|
184
|
+
browser: BrowserSignals;
|
|
185
|
+
graphics: GraphicsSignals;
|
|
186
|
+
codecs: MediaCodecsSignal;
|
|
187
|
+
locale: LocaleSignals;
|
|
188
|
+
contexts: ContextsSignals;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export interface FastBotDetectionDetails {
|
|
192
|
+
headlessChromeScreenResolution: DetectionRuleResult;
|
|
193
|
+
hasWebdriver: DetectionRuleResult;
|
|
194
|
+
hasWebdriverWritable: DetectionRuleResult;
|
|
195
|
+
hasSeleniumProperty: DetectionRuleResult;
|
|
196
|
+
hasCDP: DetectionRuleResult;
|
|
197
|
+
hasPlaywright: DetectionRuleResult;
|
|
198
|
+
hasImpossibleDeviceMemory: DetectionRuleResult;
|
|
199
|
+
hasHighCPUCount: DetectionRuleResult;
|
|
200
|
+
hasMissingChromeObject: DetectionRuleResult;
|
|
201
|
+
hasWebdriverIframe: DetectionRuleResult;
|
|
202
|
+
hasWebdriverWorker: DetectionRuleResult;
|
|
203
|
+
hasMismatchWebGLInWorker: DetectionRuleResult;
|
|
204
|
+
hasMismatchPlatformIframe: DetectionRuleResult;
|
|
205
|
+
hasMismatchPlatformWorker: DetectionRuleResult;
|
|
206
|
+
hasSwiftshaderRenderer: DetectionRuleResult;
|
|
207
|
+
hasUTCTimezone: DetectionRuleResult;
|
|
208
|
+
}
|
|
209
|
+
export interface Fingerprint {
|
|
210
|
+
signals: FingerprintSignals;
|
|
211
|
+
fsid: string;
|
|
212
|
+
nonce: string;
|
|
213
|
+
time: SignalValue<number>;
|
|
214
|
+
url: string;
|
|
215
|
+
fastBotDetection: boolean;
|
|
216
|
+
fastBotDetectionDetails: FastBotDetectionDetails;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export type DetectionSeverity = 'low' | 'medium' | 'high';
|
|
220
|
+
|
|
221
|
+
export interface DetectionRuleResult {
|
|
222
|
+
detected: boolean;
|
|
223
|
+
severity: DetectionSeverity;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export interface DetectionRule {
|
|
227
|
+
name: string;
|
|
228
|
+
severity: DetectionSeverity;
|
|
229
|
+
test: (fingerprint: Fingerprint) => boolean;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export interface CollectFingerprintOptions {
|
|
233
|
+
encrypt?: boolean;
|
|
234
|
+
timeout?: number;
|
|
235
|
+
skipWorker?: boolean;
|
|
236
|
+
}
|
|
237
|
+
|
package/.babelrc
DELETED
package/.travis.yml
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
language: node_js
|
|
2
|
-
node_js:
|
|
3
|
-
- "node"
|
|
4
|
-
dist: trusty # needs Ubuntu Trusty
|
|
5
|
-
# Note: if you switch to sudo: false, you'll need to launch chrome with --no-sandbox.
|
|
6
|
-
# See https://github.com/travis-ci/travis-ci/issues/8836
|
|
7
|
-
sudo: required
|
|
8
|
-
addons:
|
|
9
|
-
chrome: stable # have Travis install chrome stable.
|
|
10
|
-
cache:
|
|
11
|
-
npm: true
|
|
12
|
-
directories:
|
|
13
|
-
- node_modules
|
|
14
|
-
install:
|
|
15
|
-
- npm install
|
|
16
|
-
script:
|
|
17
|
-
- npm test
|