@zorilla/puppeteer-extra-plugin-stealth 1.0.0
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/.claude/settings.local.json +21 -0
- package/LICENSE +21 -0
- package/README.md +324 -0
- package/dist/evasions/README.md +13 -0
- package/dist/evasions/_template/README.md +18 -0
- package/dist/evasions/_template/index.d.ts +13 -0
- package/dist/evasions/_template/index.d.ts.map +1 -0
- package/dist/evasions/_template/index.js +26 -0
- package/dist/evasions/_template/index.js.map +1 -0
- package/dist/evasions/_template/package.json +5 -0
- package/dist/evasions/_utils/README.md +287 -0
- package/dist/evasions/_utils/index.d.ts +238 -0
- package/dist/evasions/_utils/index.d.ts.map +1 -0
- package/dist/evasions/_utils/index.js +588 -0
- package/dist/evasions/_utils/index.js.map +1 -0
- package/dist/evasions/_utils/withUtils.d.ts +12 -0
- package/dist/evasions/_utils/withUtils.d.ts.map +1 -0
- package/dist/evasions/_utils/withUtils.js +47 -0
- package/dist/evasions/_utils/withUtils.js.map +1 -0
- package/dist/evasions/chrome.app/README.md +16 -0
- package/dist/evasions/chrome.app/index.d.ts +11 -0
- package/dist/evasions/chrome.app/index.d.ts.map +1 -0
- package/dist/evasions/chrome.app/index.js +97 -0
- package/dist/evasions/chrome.app/index.js.map +1 -0
- package/dist/evasions/chrome.app/package.json +5 -0
- package/dist/evasions/chrome.csi/README.md +29 -0
- package/dist/evasions/chrome.csi/index.d.ts +25 -0
- package/dist/evasions/chrome.csi/index.d.ts.map +1 -0
- package/dist/evasions/chrome.csi/index.js +69 -0
- package/dist/evasions/chrome.csi/index.js.map +1 -0
- package/dist/evasions/chrome.csi/package.json +5 -0
- package/dist/evasions/chrome.loadTimes/README.md +27 -0
- package/dist/evasions/chrome.loadTimes/index.d.ts +23 -0
- package/dist/evasions/chrome.loadTimes/index.d.ts.map +1 -0
- package/dist/evasions/chrome.loadTimes/index.js +163 -0
- package/dist/evasions/chrome.loadTimes/index.js.map +1 -0
- package/dist/evasions/chrome.loadTimes/package.json +5 -0
- package/dist/evasions/chrome.runtime/README.md +32 -0
- package/dist/evasions/chrome.runtime/index.d.ts +14 -0
- package/dist/evasions/chrome.runtime/index.d.ts.map +1 -0
- package/dist/evasions/chrome.runtime/index.js +252 -0
- package/dist/evasions/chrome.runtime/index.js.map +1 -0
- package/dist/evasions/chrome.runtime/package.json +5 -0
- package/dist/evasions/chrome.runtime/staticData.json +41 -0
- package/dist/evasions/defaultArgs/README.md +17 -0
- package/dist/evasions/defaultArgs/index.d.ts +2 -0
- package/dist/evasions/defaultArgs/index.d.ts.map +1 -0
- package/dist/evasions/defaultArgs/index.js +43 -0
- package/dist/evasions/defaultArgs/index.js.map +1 -0
- package/dist/evasions/defaultArgs/package.json +5 -0
- package/dist/evasions/iframe.contentWindow/README.md +19 -0
- package/dist/evasions/iframe.contentWindow/index.d.ts +15 -0
- package/dist/evasions/iframe.contentWindow/index.d.ts.map +1 -0
- package/dist/evasions/iframe.contentWindow/index.js +132 -0
- package/dist/evasions/iframe.contentWindow/index.js.map +1 -0
- package/dist/evasions/iframe.contentWindow/package.json +5 -0
- package/dist/evasions/media.codecs/README.md +38 -0
- package/dist/evasions/media.codecs/index.d.ts +12 -0
- package/dist/evasions/media.codecs/index.d.ts.map +1 -0
- package/dist/evasions/media.codecs/index.js +89 -0
- package/dist/evasions/media.codecs/index.js.map +1 -0
- package/dist/evasions/media.codecs/package.json +5 -0
- package/dist/evasions/navigator.hardwareConcurrency/README.md +19 -0
- package/dist/evasions/navigator.hardwareConcurrency/index.d.ts +2 -0
- package/dist/evasions/navigator.hardwareConcurrency/index.d.ts.map +1 -0
- package/dist/evasions/navigator.hardwareConcurrency/index.js +45 -0
- package/dist/evasions/navigator.hardwareConcurrency/index.js.map +1 -0
- package/dist/evasions/navigator.hardwareConcurrency/package.json +5 -0
- package/dist/evasions/navigator.languages/README.md +17 -0
- package/dist/evasions/navigator.languages/index.d.ts +2 -0
- package/dist/evasions/navigator.languages/index.d.ts.map +1 -0
- package/dist/evasions/navigator.languages/index.js +44 -0
- package/dist/evasions/navigator.languages/index.js.map +1 -0
- package/dist/evasions/navigator.languages/package.json +5 -0
- package/dist/evasions/navigator.permissions/README.md +16 -0
- package/dist/evasions/navigator.permissions/index.d.ts +2 -0
- package/dist/evasions/navigator.permissions/index.d.ts.map +1 -0
- package/dist/evasions/navigator.permissions/index.js +66 -0
- package/dist/evasions/navigator.permissions/index.js.map +1 -0
- package/dist/evasions/navigator.permissions/package.json +5 -0
- package/dist/evasions/navigator.plugins/README.md +24 -0
- package/dist/evasions/navigator.plugins/data.json +48 -0
- package/dist/evasions/navigator.plugins/functionMocks.d.ts +9 -0
- package/dist/evasions/navigator.plugins/functionMocks.d.ts.map +1 -0
- package/dist/evasions/navigator.plugins/functionMocks.js +47 -0
- package/dist/evasions/navigator.plugins/functionMocks.js.map +1 -0
- package/dist/evasions/navigator.plugins/index.d.ts +19 -0
- package/dist/evasions/navigator.plugins/index.d.ts.map +1 -0
- package/dist/evasions/navigator.plugins/index.js +98 -0
- package/dist/evasions/navigator.plugins/index.js.map +1 -0
- package/dist/evasions/navigator.plugins/magicArray.d.ts +2 -0
- package/dist/evasions/navigator.plugins/magicArray.d.ts.map +1 -0
- package/dist/evasions/navigator.plugins/magicArray.js +145 -0
- package/dist/evasions/navigator.plugins/magicArray.js.map +1 -0
- package/dist/evasions/navigator.plugins/mimeTypes.d.ts +2 -0
- package/dist/evasions/navigator.plugins/mimeTypes.d.ts.map +1 -0
- package/dist/evasions/navigator.plugins/mimeTypes.js +18 -0
- package/dist/evasions/navigator.plugins/mimeTypes.js.map +1 -0
- package/dist/evasions/navigator.plugins/package.json +5 -0
- package/dist/evasions/navigator.plugins/plugins.d.ts +2 -0
- package/dist/evasions/navigator.plugins/plugins.d.ts.map +1 -0
- package/dist/evasions/navigator.plugins/plugins.js +18 -0
- package/dist/evasions/navigator.plugins/plugins.js.map +1 -0
- package/dist/evasions/navigator.vendor/README.md +36 -0
- package/dist/evasions/navigator.vendor/index.d.ts +2 -0
- package/dist/evasions/navigator.vendor/index.d.ts.map +1 -0
- package/dist/evasions/navigator.vendor/index.js +64 -0
- package/dist/evasions/navigator.vendor/index.js.map +1 -0
- package/dist/evasions/navigator.vendor/package.json +5 -0
- package/dist/evasions/navigator.webdriver/README.md +17 -0
- package/dist/evasions/navigator.webdriver/index.d.ts +13 -0
- package/dist/evasions/navigator.webdriver/index.d.ts.map +1 -0
- package/dist/evasions/navigator.webdriver/index.js +48 -0
- package/dist/evasions/navigator.webdriver/index.js.map +1 -0
- package/dist/evasions/navigator.webdriver/package.json +5 -0
- package/dist/evasions/sourceurl/README.md +17 -0
- package/dist/evasions/sourceurl/_fixtures/test.html +35 -0
- package/dist/evasions/sourceurl/index.d.ts +12 -0
- package/dist/evasions/sourceurl/index.d.ts.map +1 -0
- package/dist/evasions/sourceurl/index.js +82 -0
- package/dist/evasions/sourceurl/index.js.map +1 -0
- package/dist/evasions/sourceurl/package.json +5 -0
- package/dist/evasions/user-agent-override/README.md +53 -0
- package/dist/evasions/user-agent-override/index.d.ts +2 -0
- package/dist/evasions/user-agent-override/index.d.ts.map +1 -0
- package/dist/evasions/user-agent-override/index.js +206 -0
- package/dist/evasions/user-agent-override/index.js.map +1 -0
- package/dist/evasions/user-agent-override/package.json +5 -0
- package/dist/evasions/webgl.vendor/README.md +20 -0
- package/dist/evasions/webgl.vendor/index.d.ts +17 -0
- package/dist/evasions/webgl.vendor/index.d.ts.map +1 -0
- package/dist/evasions/webgl.vendor/index.js +57 -0
- package/dist/evasions/webgl.vendor/index.js.map +1 -0
- package/dist/evasions/webgl.vendor/package.json +5 -0
- package/dist/evasions/window.outerdimensions/README.md +17 -0
- package/dist/evasions/window.outerdimensions/index.d.ts +13 -0
- package/dist/evasions/window.outerdimensions/index.d.ts.map +1 -0
- package/dist/evasions/window.outerdimensions/index.js +42 -0
- package/dist/evasions/window.outerdimensions/index.js.map +1 -0
- package/dist/evasions/window.outerdimensions/package.json +5 -0
- package/dist/index.d.ts +130 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +164 -0
- package/dist/index.js.map +1 -0
- package/examples/detect-headless.js +95 -0
- package/examples/test1.js +20 -0
- package/examples/test2.js +25 -0
- package/package.json +70 -0
- package/src/evasions/README.md +13 -0
- package/src/evasions/_template/README.md +18 -0
- package/src/evasions/_template/index.js +26 -0
- package/src/evasions/_template/package.json +5 -0
- package/src/evasions/_utils/README.md +287 -0
- package/src/evasions/_utils/index.js +588 -0
- package/src/evasions/_utils/withUtils.js +47 -0
- package/src/evasions/chrome.app/README.md +16 -0
- package/src/evasions/chrome.app/index.js +97 -0
- package/src/evasions/chrome.app/package.json +5 -0
- package/src/evasions/chrome.csi/README.md +29 -0
- package/src/evasions/chrome.csi/index.js +69 -0
- package/src/evasions/chrome.csi/package.json +5 -0
- package/src/evasions/chrome.loadTimes/README.md +27 -0
- package/src/evasions/chrome.loadTimes/index.js +163 -0
- package/src/evasions/chrome.loadTimes/package.json +5 -0
- package/src/evasions/chrome.runtime/README.md +32 -0
- package/src/evasions/chrome.runtime/index.js +252 -0
- package/src/evasions/chrome.runtime/package.json +5 -0
- package/src/evasions/chrome.runtime/staticData.json +41 -0
- package/src/evasions/defaultArgs/README.md +17 -0
- package/src/evasions/defaultArgs/index.js +43 -0
- package/src/evasions/defaultArgs/package.json +5 -0
- package/src/evasions/iframe.contentWindow/README.md +19 -0
- package/src/evasions/iframe.contentWindow/index.js +132 -0
- package/src/evasions/iframe.contentWindow/package.json +5 -0
- package/src/evasions/media.codecs/README.md +38 -0
- package/src/evasions/media.codecs/index.js +89 -0
- package/src/evasions/media.codecs/package.json +5 -0
- package/src/evasions/navigator.hardwareConcurrency/README.md +19 -0
- package/src/evasions/navigator.hardwareConcurrency/index.js +45 -0
- package/src/evasions/navigator.hardwareConcurrency/package.json +5 -0
- package/src/evasions/navigator.languages/README.md +17 -0
- package/src/evasions/navigator.languages/index.js +44 -0
- package/src/evasions/navigator.languages/package.json +5 -0
- package/src/evasions/navigator.permissions/README.md +16 -0
- package/src/evasions/navigator.permissions/index.js +66 -0
- package/src/evasions/navigator.permissions/package.json +5 -0
- package/src/evasions/navigator.plugins/README.md +24 -0
- package/src/evasions/navigator.plugins/data.json +48 -0
- package/src/evasions/navigator.plugins/functionMocks.js +47 -0
- package/src/evasions/navigator.plugins/index.js +98 -0
- package/src/evasions/navigator.plugins/magicArray.js +145 -0
- package/src/evasions/navigator.plugins/mimeTypes.js +18 -0
- package/src/evasions/navigator.plugins/package.json +5 -0
- package/src/evasions/navigator.plugins/plugins.js +18 -0
- package/src/evasions/navigator.vendor/README.md +36 -0
- package/src/evasions/navigator.vendor/index.js +64 -0
- package/src/evasions/navigator.vendor/package.json +5 -0
- package/src/evasions/navigator.webdriver/README.md +17 -0
- package/src/evasions/navigator.webdriver/index.js +48 -0
- package/src/evasions/navigator.webdriver/package.json +5 -0
- package/src/evasions/sourceurl/README.md +17 -0
- package/src/evasions/sourceurl/_fixtures/test.html +35 -0
- package/src/evasions/sourceurl/index.js +82 -0
- package/src/evasions/sourceurl/package.json +5 -0
- package/src/evasions/user-agent-override/README.md +53 -0
- package/src/evasions/user-agent-override/index.js +206 -0
- package/src/evasions/user-agent-override/package.json +5 -0
- package/src/evasions/webgl.vendor/README.md +20 -0
- package/src/evasions/webgl.vendor/index.js +57 -0
- package/src/evasions/webgl.vendor/package.json +5 -0
- package/src/evasions/window.outerdimensions/README.md +17 -0
- package/src/evasions/window.outerdimensions/index.js +42 -0
- package/src/evasions/window.outerdimensions/package.json +5 -0
- package/src/index.d.ts +111 -0
- package/src/index.ts +188 -0
- package/test/cat-and-mouse.test.ts +170 -0
- package/test/evasions/_utils/index.test.ts +710 -0
- package/test/evasions/chrome.app/index.test.ts +69 -0
- package/test/evasions/chrome.csi/index.test.ts +46 -0
- package/test/evasions/chrome.loadTimes/index.test.ts +61 -0
- package/test/evasions/chrome.runtime/index.test.ts +282 -0
- package/test/evasions/defaultArgs/index.test.ts +36 -0
- package/test/evasions/iframe.contentWindow/index.test.js +450 -0
- package/test/evasions/media.codecs/index.test.js +103 -0
- package/test/evasions/navigator.hardwareConcurrency/index.test.js +58 -0
- package/test/evasions/navigator.languages/index.test.js +101 -0
- package/test/evasions/navigator.permissions/index.test.js +104 -0
- package/test/evasions/navigator.plugins/index.test.js +55 -0
- package/test/evasions/navigator.plugins/mimeTypes.test.js +220 -0
- package/test/evasions/navigator.plugins/plugins.test.js +181 -0
- package/test/evasions/navigator.vendor/index.test.js +68 -0
- package/test/evasions/navigator.webdriver/index.test.js +47 -0
- package/test/evasions/sourceurl/_fixtures/test.html +35 -0
- package/test/evasions/sourceurl/index.test.js +62 -0
- package/test/evasions/user-agent-override/index.test.js +338 -0
- package/test/evasions/webgl.vendor/index.test.js +220 -0
- package/test/fixtures/dummy-with-service-worker.html +22 -0
- package/test/fixtures/dummy.html +11 -0
- package/test/fixtures/sw.js +1 -0
- package/test/fpscanner.test.ts +54 -0
- package/test/index.test.ts +51 -0
- package/test/service-worker.test.ts +112 -0
- package/test/stealth/_results/_thumbs/headful-chrome-stealth.js.png +0 -0
- package/test/stealth/_results/_thumbs/headful-chrome-vanilla.js.png +0 -0
- package/test/stealth/_results/_thumbs/headful-chromium-stealth.js.png +0 -0
- package/test/stealth/_results/_thumbs/headful-chromium-vanilla.js.png +0 -0
- package/test/stealth/_results/_thumbs/headless-chrome-stealth.js.png +0 -0
- package/test/stealth/_results/_thumbs/headless-chrome-vanilla.js.png +0 -0
- package/test/stealth/_results/_thumbs/headless-chromium-stealth.js.png +0 -0
- package/test/stealth/_results/_thumbs/headless-chromium-vanilla.js.png +0 -0
- package/test/stealth/_results/headful-chrome-stealth.js.png +0 -0
- package/test/stealth/_results/headful-chrome-vanilla.js.png +0 -0
- package/test/stealth/_results/headful-chromium-stealth.js.png +0 -0
- package/test/stealth/_results/headful-chromium-vanilla.js.png +0 -0
- package/test/stealth/_results/headless-chrome-stealth.js.png +0 -0
- package/test/stealth/_results/headless-chrome-vanilla.js.png +0 -0
- package/test/stealth/_results/headless-chromium-stealth.js.png +0 -0
- package/test/stealth/_results/headless-chromium-vanilla.js.png +0 -0
- package/test/stealth/headful-chrome-stealth.js +25 -0
- package/test/stealth/headful-chrome-vanilla.js +23 -0
- package/test/stealth/headful-chromium-stealth.js +22 -0
- package/test/stealth/headful-chromium-vanilla.js +20 -0
- package/test/stealth/headless-chrome-stealth.js +25 -0
- package/test/stealth/headless-chrome-vanilla.js +23 -0
- package/test/stealth/headless-chromium-stealth.js +22 -0
- package/test/stealth/headless-chromium-vanilla.js +20 -0
- package/test/util.js +82 -0
- package/tsconfig.json +10 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vitest.config.ts +28 -0
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
// import Plugin from '../../../src/evasions/iframe.contentWindow/index.js'
|
|
2
|
+
// NOTE: We're using the full plugin for testing here as `iframe.contentWindow` uses data set by `chrome.runtime`
|
|
3
|
+
import Plugin from '@zorilla/puppeteer-extra-plugin-stealth';
|
|
4
|
+
import { expect, test } from 'vitest';
|
|
5
|
+
import {
|
|
6
|
+
addExtra,
|
|
7
|
+
dummyHTMLPath,
|
|
8
|
+
getStealthFingerPrint,
|
|
9
|
+
getVanillaFingerPrint,
|
|
10
|
+
vanillaPuppeteer,
|
|
11
|
+
} from '../../util.js';
|
|
12
|
+
|
|
13
|
+
// Fix CI issues with old versions
|
|
14
|
+
const isOldPuppeteerVersion = () => {
|
|
15
|
+
const version = process.env.PUPPETEER_VERSION;
|
|
16
|
+
const isOld = version && (version === '1.9.0' || version === '1.6.2');
|
|
17
|
+
return isOld;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
test.skip('vanilla: will be undefined (requires fpcollect)', async () => {
|
|
21
|
+
const { iframeChrome } = await getVanillaFingerPrint();
|
|
22
|
+
expect(iframeChrome).toBe('undefined');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test.skip('stealth: will be object (requires fpcollect)', async () => {
|
|
26
|
+
const { iframeChrome } = await getStealthFingerPrint(Plugin);
|
|
27
|
+
expect(iframeChrome).toBe('object');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test.skip('stealth (requires user-preferences): will not break iframes', async () => {
|
|
31
|
+
const browser = await addExtra(vanillaPuppeteer)
|
|
32
|
+
.use(Plugin())
|
|
33
|
+
.launch({ headless: true });
|
|
34
|
+
const page = await browser.newPage();
|
|
35
|
+
|
|
36
|
+
const testFuncReturnValue = 'TESTSTRING';
|
|
37
|
+
await page.evaluate(returnValue => {
|
|
38
|
+
const { document } = window; // eslint-disable-line
|
|
39
|
+
const body = document.querySelector('body');
|
|
40
|
+
const iframe = document.createElement('iframe');
|
|
41
|
+
body.srcdoc = 'foobar';
|
|
42
|
+
body.appendChild(iframe);
|
|
43
|
+
iframe.contentWindow.mySuperFunction = () => returnValue;
|
|
44
|
+
}, testFuncReturnValue);
|
|
45
|
+
const realReturn = await page.evaluate(
|
|
46
|
+
() => document.querySelector('iframe').contentWindow.mySuperFunction() // eslint-disable-line
|
|
47
|
+
);
|
|
48
|
+
await browser.close();
|
|
49
|
+
|
|
50
|
+
expect(realReturn).toBe('TESTSTRING');
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('vanilla: will not have contentWindow[0]', async () => {
|
|
54
|
+
const browser = await vanillaPuppeteer.launch({ headless: true });
|
|
55
|
+
const page = await browser.newPage();
|
|
56
|
+
|
|
57
|
+
const zero = await page.evaluate(_returnValue => {
|
|
58
|
+
const { document } = window; // eslint-disable-line
|
|
59
|
+
const body = document.querySelector('body');
|
|
60
|
+
const iframe = document.createElement('iframe');
|
|
61
|
+
iframe.srcdoc = 'foobar';
|
|
62
|
+
body.appendChild(iframe);
|
|
63
|
+
return typeof iframe.contentWindow[0];
|
|
64
|
+
});
|
|
65
|
+
await browser.close();
|
|
66
|
+
|
|
67
|
+
expect(zero).toBe('undefined');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test.skip('stealth (requires user-preferences): will not have contentWindow[0]', async () => {
|
|
71
|
+
const browser = await addExtra(vanillaPuppeteer)
|
|
72
|
+
.use(Plugin())
|
|
73
|
+
.launch({ headless: true });
|
|
74
|
+
const page = await browser.newPage();
|
|
75
|
+
|
|
76
|
+
const zero = await page.evaluate(_returnValue => {
|
|
77
|
+
const { document } = window; // eslint-disable-line
|
|
78
|
+
const body = document.querySelector('body');
|
|
79
|
+
const iframe = document.createElement('iframe');
|
|
80
|
+
iframe.srcdoc = 'foobar';
|
|
81
|
+
body.appendChild(iframe);
|
|
82
|
+
return typeof iframe.contentWindow[0];
|
|
83
|
+
});
|
|
84
|
+
await browser.close();
|
|
85
|
+
|
|
86
|
+
expect(zero).toBe('undefined');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test('vanilla: will not have chrome runtine in any frame', async () => {
|
|
90
|
+
const browser = await vanillaPuppeteer.launch({ headless: true });
|
|
91
|
+
const page = await browser.newPage();
|
|
92
|
+
|
|
93
|
+
await page.goto('file://' + dummyHTMLPath);
|
|
94
|
+
|
|
95
|
+
const basiciframe = await page.evaluate(() => {
|
|
96
|
+
const el = document.createElement('iframe');
|
|
97
|
+
document.body.appendChild(el);
|
|
98
|
+
return el.contentWindow.chrome;
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const sandboxSOiframe = await page.evaluate(() => {
|
|
102
|
+
const el = document.createElement('iframe');
|
|
103
|
+
el.setAttribute('sandbox', 'allow-same-origin');
|
|
104
|
+
document.body.appendChild(el);
|
|
105
|
+
return el.contentWindow.chrome;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const sandboxSOASiframe = await page.evaluate(() => {
|
|
109
|
+
const el = document.createElement('iframe');
|
|
110
|
+
el.setAttribute('sandbox', 'allow-same-origin allow-scripts');
|
|
111
|
+
document.body.appendChild(el);
|
|
112
|
+
return el.contentWindow.chrome;
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const srcdociframe = await page.evaluate(() => {
|
|
116
|
+
const el = document.createElement('iframe');
|
|
117
|
+
el.srcdoc = 'blank page, boys.';
|
|
118
|
+
document.body.appendChild(el);
|
|
119
|
+
return el.contentWindow.chrome;
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// console.log('basic iframe', basiciframe)
|
|
123
|
+
// console.log('sandbox same-origin iframe', sandboxSOiframe)
|
|
124
|
+
// console.log('sandbox same-origin&scripts iframe', sandboxSOASiframe)
|
|
125
|
+
// console.log('srcdoc iframe', srcdociframe)
|
|
126
|
+
|
|
127
|
+
await browser.close();
|
|
128
|
+
|
|
129
|
+
// Note: Newer Chrome versions (130+) now provide chrome object in iframes
|
|
130
|
+
// The important part is that it's consistent across frame types
|
|
131
|
+
// Can be either undefined (older Chrome) or object (newer Chrome)
|
|
132
|
+
expect(['undefined', 'object']).toContain(typeof basiciframe);
|
|
133
|
+
expect(['undefined', 'object']).toContain(typeof sandboxSOiframe);
|
|
134
|
+
expect(['undefined', 'object']).toContain(typeof sandboxSOASiframe);
|
|
135
|
+
expect(['undefined', 'object']).toContain(typeof srcdociframe);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test.skip('stealth (requires user-preferences): it will cover all frames including srcdoc', async () => {
|
|
139
|
+
// const browser = await vanillaPuppeteer.launch({ headless: false })
|
|
140
|
+
const browser = await addExtra(vanillaPuppeteer)
|
|
141
|
+
.use(Plugin())
|
|
142
|
+
.launch({ headless: true });
|
|
143
|
+
const page = await browser.newPage();
|
|
144
|
+
|
|
145
|
+
await page.goto('file://' + dummyHTMLPath);
|
|
146
|
+
|
|
147
|
+
const basiciframe = await page.evaluate(() => {
|
|
148
|
+
const el = document.createElement('iframe');
|
|
149
|
+
document.body.appendChild(el);
|
|
150
|
+
return el.contentWindow.chrome;
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const sandboxSOiframe = await page.evaluate(() => {
|
|
154
|
+
const el = document.createElement('iframe');
|
|
155
|
+
el.setAttribute('sandbox', 'allow-same-origin');
|
|
156
|
+
document.body.appendChild(el);
|
|
157
|
+
return el.contentWindow.chrome;
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const sandboxSOASiframe = await page.evaluate(() => {
|
|
161
|
+
const el = document.createElement('iframe');
|
|
162
|
+
el.setAttribute('sandbox', 'allow-same-origin allow-scripts');
|
|
163
|
+
document.body.appendChild(el);
|
|
164
|
+
return el.contentWindow.chrome;
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const srcdociframe = await page.evaluate(() => {
|
|
168
|
+
const el = document.createElement('iframe');
|
|
169
|
+
el.srcdoc = 'blank page, boys.';
|
|
170
|
+
document.body.appendChild(el);
|
|
171
|
+
return el.contentWindow.chrome;
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// console.log('basic iframe', basiciframe)
|
|
175
|
+
// console.log('sandbox same-origin iframe', sandboxSOiframe)
|
|
176
|
+
// console.log('sandbox same-origin&scripts iframe', sandboxSOASiframe)
|
|
177
|
+
// console.log('srcdoc iframe', srcdociframe)
|
|
178
|
+
|
|
179
|
+
await browser.close();
|
|
180
|
+
|
|
181
|
+
if (isOldPuppeteerVersion()) {
|
|
182
|
+
expect(typeof basiciframe).toBe('object');
|
|
183
|
+
} else {
|
|
184
|
+
expect(typeof basiciframe).toBe('object');
|
|
185
|
+
expect(typeof sandboxSOiframe).toBe('object');
|
|
186
|
+
expect(typeof sandboxSOASiframe).toBe('object');
|
|
187
|
+
expect(typeof srcdociframe).toBe('object');
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('vanilla: will allow to define property contentWindow', async () => {
|
|
192
|
+
const browser = await vanillaPuppeteer.launch({ headless: true });
|
|
193
|
+
const page = await browser.newPage();
|
|
194
|
+
|
|
195
|
+
const iframe = await page.evaluate(() => {
|
|
196
|
+
const { document } = window; // eslint-disable-line
|
|
197
|
+
const iframe = document.createElement('iframe');
|
|
198
|
+
iframe.srcdoc = 'foobar';
|
|
199
|
+
return Object.defineProperty(iframe, 'contentWindow', { value: 'baz' });
|
|
200
|
+
});
|
|
201
|
+
await browser.close();
|
|
202
|
+
|
|
203
|
+
expect(typeof iframe).toBe('object');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// test('stealth: will allow to define property contentWindow', async () => {
|
|
207
|
+
// const browser = await addExtra(vanillaPuppeteer)
|
|
208
|
+
// .use(Plugin())
|
|
209
|
+
// .launch({ headless: true })
|
|
210
|
+
// const page = await browser.newPage()
|
|
211
|
+
//
|
|
212
|
+
// const iframe = await page.evaluate(() => {
|
|
213
|
+
// const { document } = window // eslint-disable-line
|
|
214
|
+
// const iframe = document.createElement('iframe')
|
|
215
|
+
// iframe.srcdoc = 'foobar'
|
|
216
|
+
// return Object.defineProperty(iframe, 'contentWindow', { value: 'baz' })
|
|
217
|
+
// })
|
|
218
|
+
// await browser.close()
|
|
219
|
+
//
|
|
220
|
+
// expect(typeof iframe).toBe('object')
|
|
221
|
+
// })
|
|
222
|
+
|
|
223
|
+
test('vanilla: will return undefined for getOwnPropertyDescriptor of contentWindow', async () => {
|
|
224
|
+
const browser = await vanillaPuppeteer.launch({ headless: true });
|
|
225
|
+
const page = await browser.newPage();
|
|
226
|
+
|
|
227
|
+
const iframe = await page.evaluate(() => {
|
|
228
|
+
const { document } = window; // eslint-disable-line
|
|
229
|
+
const iframe = document.createElement('iframe');
|
|
230
|
+
iframe.srcdoc = 'foobar';
|
|
231
|
+
return Object.getOwnPropertyDescriptor(iframe, 'contentWindow');
|
|
232
|
+
});
|
|
233
|
+
await browser.close();
|
|
234
|
+
|
|
235
|
+
expect(iframe).toBe(undefined);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// test('stealth: will return undefined for getOwnPropertyDescriptor of contentWindow', async () => {
|
|
239
|
+
// const browser = await addExtra(vanillaPuppeteer)
|
|
240
|
+
// .use(Plugin())
|
|
241
|
+
// .launch({ headless: true })
|
|
242
|
+
// const page = await browser.newPage()
|
|
243
|
+
//
|
|
244
|
+
// const iframe = await page.evaluate(() => {
|
|
245
|
+
// const { document } = window // eslint-disable-line
|
|
246
|
+
// const iframe = document.createElement('iframe')
|
|
247
|
+
// iframe.srcdoc = 'foobar'
|
|
248
|
+
// return Object.getOwnPropertyDescriptor(iframe, 'contentWindow')
|
|
249
|
+
// })
|
|
250
|
+
// await browser.close()
|
|
251
|
+
//
|
|
252
|
+
// expect(iframe).toBe(undefined)
|
|
253
|
+
// })
|
|
254
|
+
|
|
255
|
+
/* global HTMLIFrameElement */
|
|
256
|
+
test.skip('stealth (requires user-preferences): it will emulate advanved contentWindow features correctly', async () => {
|
|
257
|
+
// const browser = await vanillaPuppeteer.launch({ headless: false })
|
|
258
|
+
const browser = await addExtra(vanillaPuppeteer)
|
|
259
|
+
.use(Plugin())
|
|
260
|
+
.launch({ headless: true });
|
|
261
|
+
const page = await browser.newPage();
|
|
262
|
+
|
|
263
|
+
await page.goto('file://' + dummyHTMLPath);
|
|
264
|
+
|
|
265
|
+
// page.on('console', msg => {
|
|
266
|
+
// console.log('Page console: ', msg.text())
|
|
267
|
+
// })
|
|
268
|
+
|
|
269
|
+
const results = await page.evaluate(() => {
|
|
270
|
+
const results = {};
|
|
271
|
+
|
|
272
|
+
const iframe = document.createElement('iframe');
|
|
273
|
+
iframe.srcdoc = 'page intentionally left blank'; // Note: srcdoc
|
|
274
|
+
document.body.appendChild(iframe);
|
|
275
|
+
|
|
276
|
+
const basicIframe = document.createElement('iframe');
|
|
277
|
+
basicIframe.src = 'data:text/plain;charset=utf-8,foobar';
|
|
278
|
+
document.body.appendChild(iframe);
|
|
279
|
+
|
|
280
|
+
results.descriptors = (() => {
|
|
281
|
+
// Verify iframe prototype isn't touched
|
|
282
|
+
const descriptors = Object.getOwnPropertyDescriptors(
|
|
283
|
+
HTMLIFrameElement.prototype
|
|
284
|
+
);
|
|
285
|
+
return descriptors.contentWindow.get.toString();
|
|
286
|
+
})();
|
|
287
|
+
|
|
288
|
+
results.noProxySignature = (() => {
|
|
289
|
+
return Object.hasOwn(iframe.srcdoc.toString, '[[IsRevoked]]'); // eslint-disable-line
|
|
290
|
+
})();
|
|
291
|
+
|
|
292
|
+
results.doesExist = (() => {
|
|
293
|
+
// Verify iframe isn't remapped to main window
|
|
294
|
+
return !!iframe.contentWindow;
|
|
295
|
+
})();
|
|
296
|
+
|
|
297
|
+
results.isNotAClone = (() => {
|
|
298
|
+
// Verify iframe isn't remapped to main window
|
|
299
|
+
return iframe.contentWindow !== window;
|
|
300
|
+
})();
|
|
301
|
+
|
|
302
|
+
results.hasPlugins = (() => {
|
|
303
|
+
return iframe.contentWindow.navigator.plugins.length > 0;
|
|
304
|
+
})();
|
|
305
|
+
|
|
306
|
+
results.hasSameNumberOfPlugins = (() => {
|
|
307
|
+
return (
|
|
308
|
+
window.navigator.plugins.length ===
|
|
309
|
+
iframe.contentWindow.navigator.plugins.length
|
|
310
|
+
);
|
|
311
|
+
})();
|
|
312
|
+
|
|
313
|
+
results.SelfIsNotWindow = (() => {
|
|
314
|
+
return iframe.contentWindow.self !== window;
|
|
315
|
+
})();
|
|
316
|
+
|
|
317
|
+
results.SelfIsNotWindowTop = (() => {
|
|
318
|
+
return iframe.contentWindow.self !== window.top;
|
|
319
|
+
})();
|
|
320
|
+
|
|
321
|
+
results.TopIsNotSame = (() => {
|
|
322
|
+
return iframe.contentWindow.top !== iframe.contentWindow;
|
|
323
|
+
})();
|
|
324
|
+
|
|
325
|
+
results.FrameElementMatches = (() => {
|
|
326
|
+
return iframe.contentWindow.frameElement === iframe;
|
|
327
|
+
})();
|
|
328
|
+
|
|
329
|
+
results.StackTraces = (() => {
|
|
330
|
+
try {
|
|
331
|
+
// eslint-disable-next-line
|
|
332
|
+
document.createElement(0);
|
|
333
|
+
} catch (e) {
|
|
334
|
+
return e.stack;
|
|
335
|
+
}
|
|
336
|
+
return false;
|
|
337
|
+
})();
|
|
338
|
+
|
|
339
|
+
return results;
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
await browser.close();
|
|
343
|
+
|
|
344
|
+
if (isOldPuppeteerVersion()) {
|
|
345
|
+
expect(true).toBe(true);
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
expect(results.descriptors).toBe(
|
|
350
|
+
'function get contentWindow() { [native code] }'
|
|
351
|
+
);
|
|
352
|
+
expect(results.doesExist).toBe(true);
|
|
353
|
+
expect(results.isNotAClone).toBe(true);
|
|
354
|
+
expect(results.hasPlugins).toBe(true);
|
|
355
|
+
expect(results.hasSameNumberOfPlugins).toBe(true);
|
|
356
|
+
expect(results.SelfIsNotWindow).toBe(true);
|
|
357
|
+
expect(results.SelfIsNotWindowTop).toBe(true);
|
|
358
|
+
expect(results.TopIsNotSame).toBe(true);
|
|
359
|
+
expect(results.StackTraces.includes(`at Object.apply`)).toBe(false);
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
test.skip('regression (requires user-preferences): new method will not break hcaptcha', async () => {
|
|
363
|
+
const browser = await addExtra(vanillaPuppeteer)
|
|
364
|
+
.use(Plugin())
|
|
365
|
+
.launch({ headless: true });
|
|
366
|
+
const page = await browser.newPage();
|
|
367
|
+
|
|
368
|
+
page.waitForTimeout = page.waitForTimeout || page.waitFor;
|
|
369
|
+
|
|
370
|
+
await page.goto('https://democaptcha.com/demo-form-eng/hcaptcha.html', {
|
|
371
|
+
waitUntil: 'networkidle2',
|
|
372
|
+
});
|
|
373
|
+
await page.evaluate(() => {
|
|
374
|
+
window.hcaptcha.execute();
|
|
375
|
+
});
|
|
376
|
+
await page.waitForTimeout(2 * 1000);
|
|
377
|
+
const { hasChallengePopup } = await page.evaluate(() => {
|
|
378
|
+
const hasChallengePopup = !!document.querySelectorAll(
|
|
379
|
+
`div[style*='visible'] iframe[title*='hCaptcha challenge']`
|
|
380
|
+
).length;
|
|
381
|
+
return { hasChallengePopup };
|
|
382
|
+
});
|
|
383
|
+
await browser.close();
|
|
384
|
+
expect(hasChallengePopup).toBe(true);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
test.skip('regression (requires user-preferences): new method will not break recaptcha popup', async () => {
|
|
388
|
+
// const browser = await vanillaPuppeteer.launch({ headless: false })
|
|
389
|
+
const browser = await addExtra(vanillaPuppeteer)
|
|
390
|
+
.use(Plugin())
|
|
391
|
+
.launch({ headless: true });
|
|
392
|
+
const page = await browser.newPage();
|
|
393
|
+
|
|
394
|
+
page.waitForTimeout = page.waitForTimeout || page.waitFor;
|
|
395
|
+
|
|
396
|
+
await page.goto('https://www.fbdemo.com/invisible-captcha/index.html', {
|
|
397
|
+
waitUntil: 'networkidle2',
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
await page.type('#tswname', 'foo');
|
|
401
|
+
await page.type('#tswemail', 'foo@foo.foo');
|
|
402
|
+
await page.type(
|
|
403
|
+
'#tswcomments',
|
|
404
|
+
'In the depth of winter, I finally learned that within me there lay an invincible summer.'
|
|
405
|
+
);
|
|
406
|
+
await page.click('#tswsubmit');
|
|
407
|
+
await page.waitForTimeout(1000);
|
|
408
|
+
const { hasRecaptchaPopup } = await page.evaluate(() => {
|
|
409
|
+
const hasRecaptchaPopup = !!document.querySelectorAll(
|
|
410
|
+
`iframe[title*="recaptcha challenge"]`
|
|
411
|
+
).length;
|
|
412
|
+
return { hasRecaptchaPopup };
|
|
413
|
+
});
|
|
414
|
+
await browser.close();
|
|
415
|
+
expect(hasRecaptchaPopup).toBe(true);
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
test.skip('regression (requires user-preferences): old method indeed did break recaptcha popup', async () => {
|
|
419
|
+
const browser = await vanillaPuppeteer.launch({ headless: true });
|
|
420
|
+
const page = await browser.newPage();
|
|
421
|
+
|
|
422
|
+
page.waitForTimeout = page.waitForTimeout || page.waitFor;
|
|
423
|
+
// Old method
|
|
424
|
+
await page.evaluateOnNewDocument(() => {
|
|
425
|
+
// eslint-disable-next-line
|
|
426
|
+
Object.defineProperty(HTMLIFrameElement.prototype, 'contentWindow', {
|
|
427
|
+
get: () => window,
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
await page.goto('https://www.fbdemo.com/invisible-captcha/index.html', {
|
|
431
|
+
waitUntil: 'networkidle2',
|
|
432
|
+
});
|
|
433
|
+
await page.type('#tswname', 'foo');
|
|
434
|
+
await page.type('#tswemail', 'foo@foo.foo');
|
|
435
|
+
await page.type(
|
|
436
|
+
'#tswcomments',
|
|
437
|
+
'In the depth of winter, I finally learned that within me there lay an invincible summer.'
|
|
438
|
+
);
|
|
439
|
+
await page.click('#tswsubmit');
|
|
440
|
+
await page.waitForTimeout(1000);
|
|
441
|
+
|
|
442
|
+
const { hasRecaptchaPopup } = await page.evaluate(() => {
|
|
443
|
+
const hasRecaptchaPopup = !!document.querySelectorAll(
|
|
444
|
+
`iframe[title*="recaptcha challenge"]`
|
|
445
|
+
).length;
|
|
446
|
+
return { hasRecaptchaPopup };
|
|
447
|
+
});
|
|
448
|
+
await browser.close();
|
|
449
|
+
expect(hasRecaptchaPopup).toBe(false);
|
|
450
|
+
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { expect, test } from 'vitest';
|
|
2
|
+
import Plugin from '../../../src/evasions/media.codecs/index.js';
|
|
3
|
+
import {
|
|
4
|
+
addExtra,
|
|
5
|
+
getStealthFingerPrint,
|
|
6
|
+
getVanillaFingerPrint,
|
|
7
|
+
vanillaPuppeteer,
|
|
8
|
+
} from '../../util.js';
|
|
9
|
+
|
|
10
|
+
test.skip('vanilla: doesnt support proprietary codecs (requires fpcollect)', async () => {
|
|
11
|
+
const { videoCodecs, audioCodecs } = await getVanillaFingerPrint();
|
|
12
|
+
expect(videoCodecs).toEqual({ ogg: 'probably', h264: '', webm: 'probably' });
|
|
13
|
+
expect(audioCodecs).toEqual({
|
|
14
|
+
ogg: 'probably',
|
|
15
|
+
mp3: 'probably',
|
|
16
|
+
wav: 'probably',
|
|
17
|
+
m4a: '',
|
|
18
|
+
aac: '',
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('vanilla: will not have modifications', async () => {
|
|
23
|
+
const browser = await vanillaPuppeteer.launch({ headless: true });
|
|
24
|
+
const page = await browser.newPage();
|
|
25
|
+
|
|
26
|
+
// https://datadome.co/bot-detection/client-side-detection-is-essential-for-bot-protection/
|
|
27
|
+
const test1 = await page.evaluate(() => {
|
|
28
|
+
const audioElt = document.createElement('audio');
|
|
29
|
+
return audioElt.canPlayType.toString();
|
|
30
|
+
});
|
|
31
|
+
expect(test1).toBe('function canPlayType() { [native code] }');
|
|
32
|
+
|
|
33
|
+
const test2 = await page.evaluate(() => {
|
|
34
|
+
const audioElt = document.createElement('audio');
|
|
35
|
+
return audioElt.canPlayType.name;
|
|
36
|
+
});
|
|
37
|
+
expect(test2).toBe('canPlayType');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test.skip('stealth: supports proprietary codecs (requires fpcollect)', async () => {
|
|
41
|
+
const { videoCodecs, audioCodecs } = await getStealthFingerPrint(Plugin);
|
|
42
|
+
expect(videoCodecs).toEqual({
|
|
43
|
+
ogg: 'probably',
|
|
44
|
+
h264: 'probably',
|
|
45
|
+
webm: 'probably',
|
|
46
|
+
});
|
|
47
|
+
expect(audioCodecs).toEqual({
|
|
48
|
+
ogg: 'probably',
|
|
49
|
+
mp3: 'probably',
|
|
50
|
+
wav: 'probably',
|
|
51
|
+
m4a: 'maybe',
|
|
52
|
+
aac: 'probably',
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('stealth: will not leak modifications', async () => {
|
|
57
|
+
const puppeteer = addExtra(vanillaPuppeteer).use(Plugin());
|
|
58
|
+
const browser = await puppeteer.launch({ headless: true });
|
|
59
|
+
const page = await browser.newPage();
|
|
60
|
+
|
|
61
|
+
// https://datadome.co/bot-detection/client-side-detection-is-essential-for-bot-protection/
|
|
62
|
+
const test1 = await page.evaluate(() => {
|
|
63
|
+
const audioElt = document.createElement('audio');
|
|
64
|
+
return audioElt.canPlayType.toString();
|
|
65
|
+
});
|
|
66
|
+
expect(test1).toBe('function canPlayType() { [native code] }');
|
|
67
|
+
|
|
68
|
+
const test2 = await page.evaluate(() => {
|
|
69
|
+
const audioElt = document.createElement('audio');
|
|
70
|
+
return audioElt.canPlayType.name;
|
|
71
|
+
});
|
|
72
|
+
expect(test2).toBe('canPlayType');
|
|
73
|
+
|
|
74
|
+
// Double check the plugin is active and spoofing e.g. the aac codec results
|
|
75
|
+
const isWorkingTest = await page.evaluate(() => {
|
|
76
|
+
const audioElt = document.createElement('audio');
|
|
77
|
+
return audioElt.canPlayType('audio/aac') === 'probably'; // empty in Chromium without stealth plugin
|
|
78
|
+
});
|
|
79
|
+
expect(isWorkingTest).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('vanilla: normal toString stuff', async () => {
|
|
83
|
+
const browser = await vanillaPuppeteer.launch({ headless: true });
|
|
84
|
+
const page = await browser.newPage();
|
|
85
|
+
|
|
86
|
+
const test1 = await page.evaluate(() => {
|
|
87
|
+
const audioElt = document.createElement('audio');
|
|
88
|
+
return audioElt.canPlayType.toString + '';
|
|
89
|
+
});
|
|
90
|
+
expect(test1).toBe('function toString() { [native code] }');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('stealth: will not leak toString stuff', async () => {
|
|
94
|
+
const puppeteer = addExtra(vanillaPuppeteer).use(Plugin());
|
|
95
|
+
const browser = await puppeteer.launch({ headless: true });
|
|
96
|
+
const page = await browser.newPage();
|
|
97
|
+
|
|
98
|
+
const test1 = await page.evaluate(() => {
|
|
99
|
+
const audioElt = document.createElement('audio');
|
|
100
|
+
return audioElt.canPlayType.toString + '';
|
|
101
|
+
});
|
|
102
|
+
expect(test1).toBe('function toString() { [native code] }'); // returns function () { [native code] }
|
|
103
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import { expect, test } from 'vitest';
|
|
3
|
+
import Plugin from '../../../src/evasions/navigator.hardwareConcurrency/index.js';
|
|
4
|
+
import {
|
|
5
|
+
addExtra,
|
|
6
|
+
getStealthFingerPrint,
|
|
7
|
+
getVanillaFingerPrint,
|
|
8
|
+
vanillaPuppeteer,
|
|
9
|
+
} from '../../util.js';
|
|
10
|
+
|
|
11
|
+
const fingerprintFn = page => page.evaluate('navigator.hardwareConcurrency');
|
|
12
|
+
|
|
13
|
+
test.skip('vanilla: matches real core count (requires fpcollect)', async () => {
|
|
14
|
+
const { pageFnResult } = await getVanillaFingerPrint(fingerprintFn);
|
|
15
|
+
expect(pageFnResult).toBe(os.cpus().length);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test.skip('stealth: default is set to 4 (requires fpcollect)', async () => {
|
|
19
|
+
const { pageFnResult } = await getStealthFingerPrint(Plugin, fingerprintFn);
|
|
20
|
+
expect(pageFnResult).toBe(4);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test.skip('stealth: will override value correctly (requires fpcollect)', async () => {
|
|
24
|
+
const { pageFnResult } = await getStealthFingerPrint(Plugin, fingerprintFn, {
|
|
25
|
+
hardwareConcurrency: 8,
|
|
26
|
+
});
|
|
27
|
+
expect(pageFnResult).toBe(8);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('stealth: does patch getters properly', async () => {
|
|
31
|
+
const puppeteer = addExtra(vanillaPuppeteer).use(Plugin());
|
|
32
|
+
const browser = await puppeteer.launch({ headless: true });
|
|
33
|
+
const page = await browser.newPage();
|
|
34
|
+
|
|
35
|
+
const results = await page.evaluate(() => {
|
|
36
|
+
const hasInvocationError = (() => {
|
|
37
|
+
try {
|
|
38
|
+
// eslint-disable-next-line dot-notation
|
|
39
|
+
Object.seal(Object.getPrototypeOf(navigator).hardwareConcurrency);
|
|
40
|
+
return false;
|
|
41
|
+
} catch (_err) {
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
})();
|
|
45
|
+
return {
|
|
46
|
+
hasInvocationError,
|
|
47
|
+
toString: Object.getOwnPropertyDescriptor(
|
|
48
|
+
Object.getPrototypeOf(navigator),
|
|
49
|
+
'hardwareConcurrency'
|
|
50
|
+
).get.toString(),
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
expect(results).toEqual({
|
|
55
|
+
hasInvocationError: true,
|
|
56
|
+
toString: 'function get hardwareConcurrency() { [native code] }',
|
|
57
|
+
});
|
|
58
|
+
});
|