jumpy-lion 0.1.5 → 0.1.6-beta.1
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 +13 -0
- package/dist/browser-controller.d.ts.map +1 -1
- package/dist/browser-controller.js +52 -2
- package/dist/browser-controller.js.map +1 -1
- package/dist/browser-plugin.d.ts +31 -0
- package/dist/browser-plugin.d.ts.map +1 -1
- package/dist/browser-plugin.js +76 -1
- package/dist/browser-plugin.js.map +1 -1
- package/dist/browser-process/anti-detect-browser.d.ts +56 -0
- package/dist/browser-process/anti-detect-browser.d.ts.map +1 -0
- package/dist/browser-process/anti-detect-browser.js +134 -0
- package/dist/browser-process/anti-detect-browser.js.map +1 -0
- package/dist/browser-process/anti-detect-config.d.ts +84 -0
- package/dist/browser-process/anti-detect-config.d.ts.map +1 -0
- package/dist/browser-process/anti-detect-config.js +178 -0
- package/dist/browser-process/anti-detect-config.js.map +1 -0
- package/dist/browser-process/browser.d.ts +19 -0
- package/dist/browser-process/browser.d.ts.map +1 -1
- package/dist/browser-process/browser.js +83 -4
- package/dist/browser-process/browser.js.map +1 -1
- package/dist/browser-process/get-chrome-executable.d.ts +7 -0
- package/dist/browser-process/get-chrome-executable.d.ts.map +1 -1
- package/dist/browser-process/get-chrome-executable.js +42 -0
- package/dist/browser-process/get-chrome-executable.js.map +1 -1
- package/dist/browser-process/index.d.ts +4 -1
- package/dist/browser-process/index.d.ts.map +1 -1
- package/dist/browser-process/index.js +3 -1
- package/dist/browser-process/index.js.map +1 -1
- package/dist/crawler.d.ts +2 -0
- package/dist/crawler.d.ts.map +1 -1
- package/dist/crawler.js +5 -2
- package/dist/crawler.js.map +1 -1
- package/dist/fingerprinting/fingerprint-injector.d.ts +39 -0
- package/dist/fingerprinting/fingerprint-injector.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-injector.js +141 -50
- package/dist/fingerprinting/fingerprint-injector.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.js +16 -0
- package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.js +3 -2
- package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js +18 -10
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/index.d.ts +1 -1
- package/dist/fingerprinting/fingerprint-overrides/index.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/index.js +1 -1
- package/dist/fingerprinting/fingerprint-overrides/index.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js +5 -8
- package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.d.ts +12 -1
- package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.js +27 -22
- package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js +86 -28
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.js +165 -33
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/storage-consistency.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/storage-consistency.js +10 -8
- package/dist/fingerprinting/fingerprint-overrides/storage-consistency.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/timing-consistency.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/timing-consistency.js +9 -7
- package/dist/fingerprinting/fingerprint-overrides/timing-consistency.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.js +6 -6
- package/dist/fingerprinting/fingerprint-overrides/utils.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/utils.js +44 -1
- package/dist/fingerprinting/fingerprint-overrides/utils.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js +43 -1
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.js +9 -1
- package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js +14 -3
- package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js.map +1 -1
- package/dist/fingerprinting/non-apify-fingerprint-generator.d.ts +32 -0
- package/dist/fingerprinting/non-apify-fingerprint-generator.d.ts.map +1 -0
- package/dist/fingerprinting/non-apify-fingerprint-generator.js +480 -0
- package/dist/fingerprinting/non-apify-fingerprint-generator.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +11 -2
- package/scripts/postinstall.cjs +242 -0
|
@@ -33,15 +33,18 @@ export const createStealthScript = () => {
|
|
|
33
33
|
});
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
36
|
+
// Use centralized stable hash from __stealth store (set up by utils.ts preamble).
|
|
37
|
+
// Falls back to a UA+screen hash so the module works even if utils.ts somehow
|
|
38
|
+
// runs after this script (should not happen given injection order).
|
|
39
|
+
const _ss = typeof __stealth !== 'undefined' ? __stealth : {};
|
|
40
|
+
const sessionSeed = (_ss.stableHash
|
|
41
|
+
? _ss.stableHash(0xCAFE9001)
|
|
42
|
+
: (() => {
|
|
43
|
+
const ua = navigator.userAgent || '';
|
|
44
|
+
const s = window.screen;
|
|
45
|
+
return ua.length + (s.width || 0) + (s.height || 0);
|
|
46
|
+
})()
|
|
47
|
+
);
|
|
45
48
|
|
|
46
49
|
// Helper to safely define property with guards
|
|
47
50
|
const safeDefineProperty = (obj, prop, descriptor) => {
|
|
@@ -84,11 +87,13 @@ export const createStealthScript = () => {
|
|
|
84
87
|
|
|
85
88
|
// 3. WebDriver and Automation Flags Removal (2025)
|
|
86
89
|
const removeAutomationFlags = () => {
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
|
|
90
|
+
// NOTE: navigator.webdriver is NOT overridden here.
|
|
91
|
+
// The Chromium C++ patch (Anti-Detect 0006) makes navigator.webdriver
|
|
92
|
+
// unconditionally return false at the prototype level. Adding a JS own
|
|
93
|
+
// property here would make navigator.hasOwnProperty('webdriver') === true
|
|
94
|
+
// and Object.getOwnPropertyDescriptor(navigator,'webdriver') return a
|
|
95
|
+
// descriptor, both of which are detectable tells that don't exist in real
|
|
96
|
+
// Chrome. The C++ patch is the correct and sufficient fix.
|
|
92
97
|
|
|
93
98
|
// Remove automation indicators
|
|
94
99
|
const automationProperties = [
|
|
@@ -113,6 +118,10 @@ export const createStealthScript = () => {
|
|
|
113
118
|
} catch (e) {}
|
|
114
119
|
});
|
|
115
120
|
|
|
121
|
+
// Ensure Error.stackTraceLimit is the V8 default (10).
|
|
122
|
+
// Some automation frameworks change this value; FingerprintJS checks it.
|
|
123
|
+
try { if (typeof Error.stackTraceLimit !== 'undefined') Error.stackTraceLimit = 10; } catch (e) {}
|
|
124
|
+
|
|
116
125
|
// Ensure window.chrome exists (handled more fully by spoofChromeRuntime)
|
|
117
126
|
// NOTE: Removed stack-trace-based chrome getter that created new Error()
|
|
118
127
|
// on every access - expensive and broken since stack sanitization removes
|
|
@@ -205,6 +214,8 @@ export const createStealthScript = () => {
|
|
|
205
214
|
Object.defineProperty(arr, 'item', { value: (index) => arr[index] || null, writable: false, enumerable: false });
|
|
206
215
|
Object.defineProperty(arr, 'namedItem', { value: (name) => arr[name] || null, writable: false, enumerable: false });
|
|
207
216
|
Object.defineProperty(arr, 'refresh', { value: () => {}, writable: false, enumerable: false });
|
|
217
|
+
// Allow for...of iteration — checked by DataDome and FingerprintJS Pro
|
|
218
|
+
arr[Symbol.iterator] = function* () { for (let i = 0; i < fakePlugins.length; i++) yield arr[i]; };
|
|
208
219
|
return arr;
|
|
209
220
|
};
|
|
210
221
|
safeDefineGetter(navigator, 'plugins', pluginsGetter);
|
|
@@ -317,13 +328,11 @@ export const createStealthScript = () => {
|
|
|
317
328
|
getManifest: () => ({}),
|
|
318
329
|
// Real Chrome extension IDs are 32 lowercase alpha chars (a-p, base16 with a-p)
|
|
319
330
|
id: undefined,
|
|
320
|
-
connect: ()
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
postMessage: () => {}
|
|
326
|
-
}),
|
|
331
|
+
connect: function() {
|
|
332
|
+
// Real Chrome throws this exact error when no extension is receiving
|
|
333
|
+
// DataDome and PerimeterX specifically test this error message
|
|
334
|
+
throw new Error('Could not establish connection. Receiving end does not exist.');
|
|
335
|
+
},
|
|
327
336
|
sendMessage: () => {},
|
|
328
337
|
getURL: (path) => '',
|
|
329
338
|
onConnect: { addListener: () => {}, removeListener: () => {} },
|
|
@@ -376,11 +385,17 @@ export const createStealthScript = () => {
|
|
|
376
385
|
}
|
|
377
386
|
|
|
378
387
|
// chrome.csi() - Chrome-specific, returns page load timing info
|
|
388
|
+
// Values are pre-computed from session seed so they're stable across calls.
|
|
389
|
+
// Real Chrome returns consistent timing per page load; Math.random() is detectable.
|
|
379
390
|
if (window.chrome && !window.chrome.csi) {
|
|
391
|
+
const _csiRng = (_ss.createRNG ? _ss.createRNG(sessionSeed ^ 0x1001) : (() => { let x = sessionSeed ^ 0x1001; return () => { x = (x * 1664525 + 1013904223) >>> 0; return x / 4294967296; }; })());
|
|
392
|
+
const _csiLoadOffset = 500 + _csiRng() * 2000;
|
|
393
|
+
const _csiStartOffset = 1000 + _csiRng() * 3000;
|
|
380
394
|
window.chrome.csi = function() {
|
|
395
|
+
const now = Date.now();
|
|
381
396
|
return {
|
|
382
|
-
onloadT:
|
|
383
|
-
startE:
|
|
397
|
+
onloadT: now - _csiLoadOffset,
|
|
398
|
+
startE: now - _csiStartOffset,
|
|
384
399
|
pageT: performance.now(),
|
|
385
400
|
tran: 15, // Normal navigation
|
|
386
401
|
};
|
|
@@ -388,20 +403,30 @@ export const createStealthScript = () => {
|
|
|
388
403
|
}
|
|
389
404
|
|
|
390
405
|
// chrome.loadTimes() - Chrome-specific, returns load timing info
|
|
406
|
+
// Pre-computed offsets from session seed for stability across calls.
|
|
391
407
|
if (window.chrome && !window.chrome.loadTimes) {
|
|
408
|
+
const _ltRng = (_ss.createRNG ? _ss.createRNG(sessionSeed ^ 0x1002) : (() => { let x = sessionSeed ^ 0x1002; return () => { x = (x * 1664525 + 1013904223) >>> 0; return x / 4294967296; }; })());
|
|
409
|
+
const _ltOffsets = {
|
|
410
|
+
commit: _ltRng() * 2,
|
|
411
|
+
finishDoc: _ltRng() * 1,
|
|
412
|
+
finishLoad: _ltRng() * 0.5,
|
|
413
|
+
firstPaint: _ltRng() * 1.5,
|
|
414
|
+
request: _ltRng() * 3,
|
|
415
|
+
startLoad: _ltRng() * 2.5,
|
|
416
|
+
};
|
|
392
417
|
window.chrome.loadTimes = function() {
|
|
393
418
|
const now = Date.now() / 1000;
|
|
394
419
|
return {
|
|
395
|
-
commitLoadTime: now -
|
|
420
|
+
commitLoadTime: now - _ltOffsets.commit,
|
|
396
421
|
connectionInfo: 'h2',
|
|
397
|
-
finishDocumentLoadTime: now -
|
|
398
|
-
finishLoadTime: now -
|
|
422
|
+
finishDocumentLoadTime: now - _ltOffsets.finishDoc,
|
|
423
|
+
finishLoadTime: now - _ltOffsets.finishLoad,
|
|
399
424
|
firstPaintAfterLoadTime: 0,
|
|
400
|
-
firstPaintTime: now -
|
|
425
|
+
firstPaintTime: now - _ltOffsets.firstPaint,
|
|
401
426
|
navigationType: 'Other',
|
|
402
427
|
npnNegotiatedProtocol: 'h2',
|
|
403
|
-
requestTime: now -
|
|
404
|
-
startLoadTime: now -
|
|
428
|
+
requestTime: now - _ltOffsets.request,
|
|
429
|
+
startLoadTime: now - _ltOffsets.startLoad,
|
|
405
430
|
wasAlternateProtocolAvailable: false,
|
|
406
431
|
wasFetchedViaSpdy: true,
|
|
407
432
|
wasNpnNegotiated: true,
|
|
@@ -622,8 +647,10 @@ export const createStealthScript = () => {
|
|
|
622
647
|
const originalGetGamepads = navigator.getGamepads;
|
|
623
648
|
if (originalGetGamepads) {
|
|
624
649
|
navigator.getGamepads = function() {
|
|
625
|
-
//
|
|
626
|
-
|
|
650
|
+
// Real Chrome returns GamepadList with 4 null slots when no gamepads
|
|
651
|
+
// connected — NOT an empty array. [] vs [null,null,null,null] is a
|
|
652
|
+
// checked difference between headed Chrome and headless/Chromium.
|
|
653
|
+
return [null, null, null, null];
|
|
627
654
|
};
|
|
628
655
|
}
|
|
629
656
|
};
|
|
@@ -922,10 +949,112 @@ export const createStealthScript = () => {
|
|
|
922
949
|
if (_s5.utils) _s5.utils.registerNativeFunction(window.postMessage, 'postMessage');
|
|
923
950
|
};
|
|
924
951
|
|
|
952
|
+
// 30. Document Visibility Spoofing
|
|
953
|
+
// hasFocus() and visibilityState were only patched inside datadome-bypass.ts,
|
|
954
|
+
// meaning Cloudflare / Akamai / PerimeterX saw raw headless values. Move them
|
|
955
|
+
// here so all crawls benefit.
|
|
956
|
+
const spoofDocumentVisibility = () => {
|
|
957
|
+
try {
|
|
958
|
+
Object.defineProperty(document, 'hidden', { get: () => false, configurable: true });
|
|
959
|
+
Object.defineProperty(document, 'visibilityState', { get: () => 'visible', configurable: true });
|
|
960
|
+
} catch (e) {}
|
|
961
|
+
|
|
962
|
+
document.hasFocus = function() { return true; };
|
|
963
|
+
try {
|
|
964
|
+
Object.defineProperty(document.hasFocus, 'toString', {
|
|
965
|
+
value: () => 'function hasFocus() { [native code] }',
|
|
966
|
+
configurable: true
|
|
967
|
+
});
|
|
968
|
+
} catch (e) {}
|
|
969
|
+
|
|
970
|
+
// Suppress CDP-lifecycle-driven visibilitychange events that expose headless state
|
|
971
|
+
const origAEL = document.addEventListener.bind(document);
|
|
972
|
+
const _hiddenEvtHandler = (e) => {
|
|
973
|
+
if (e.type === 'visibilitychange') { e.stopImmediatePropagation(); }
|
|
974
|
+
};
|
|
975
|
+
origAEL('visibilitychange', _hiddenEvtHandler, true);
|
|
976
|
+
};
|
|
977
|
+
|
|
978
|
+
// 31. Encrypted Media Extensions (Widevine) Spoofing
|
|
979
|
+
// Vanilla Chromium rejects requestMediaKeySystemAccess('com.widevine.alpha')
|
|
980
|
+
// with NotSupportedError. Real Chrome ships Widevine L3 and resolves.
|
|
981
|
+
// This is one of the most reliable Chrome-vs-Chromium signals (Cloudflare, FPjs, CreepJS).
|
|
982
|
+
const spoofEME = () => {
|
|
983
|
+
if (typeof navigator.requestMediaKeySystemAccess !== 'function') return;
|
|
984
|
+
|
|
985
|
+
const _origRMKSA = navigator.requestMediaKeySystemAccess.bind(navigator);
|
|
986
|
+
|
|
987
|
+
const _fakeRMKSA = function requestMediaKeySystemAccess(keySystem, configs) {
|
|
988
|
+
if (keySystem === 'com.widevine.alpha') {
|
|
989
|
+
const cfg = (Array.isArray(configs) && configs[0]) ? configs[0] : {};
|
|
990
|
+
const resolvedCfg = {
|
|
991
|
+
label: cfg.label || '',
|
|
992
|
+
initDataTypes: cfg.initDataTypes || ['cenc'],
|
|
993
|
+
audioCapabilities: cfg.audioCapabilities || [
|
|
994
|
+
{ contentType: 'audio/mp4;codecs="mp4a.40.2"', robustness: '' }
|
|
995
|
+
],
|
|
996
|
+
videoCapabilities: cfg.videoCapabilities || [
|
|
997
|
+
{ contentType: 'video/mp4;codecs="avc1.42E01E"', robustness: '' }
|
|
998
|
+
],
|
|
999
|
+
distinctiveIdentifier: 'not-allowed',
|
|
1000
|
+
persistentState: 'not-allowed',
|
|
1001
|
+
sessionTypes: ['temporary']
|
|
1002
|
+
};
|
|
1003
|
+
|
|
1004
|
+
const fakeMKS = {
|
|
1005
|
+
setServerCertificate: () => Promise.resolve(true),
|
|
1006
|
+
createSession: function(sessionType) {
|
|
1007
|
+
const sess = {
|
|
1008
|
+
sessionId: '',
|
|
1009
|
+
expiration: NaN,
|
|
1010
|
+
closed: new Promise(() => {}),
|
|
1011
|
+
keyStatuses: new Map(),
|
|
1012
|
+
onkeystatuseschange: null,
|
|
1013
|
+
onmessage: null,
|
|
1014
|
+
generateRequest: () => Promise.reject(new DOMException('InvalidStateError', 'InvalidStateError')),
|
|
1015
|
+
load: () => Promise.resolve(false),
|
|
1016
|
+
update: () => Promise.reject(new DOMException('InvalidStateError', 'InvalidStateError')),
|
|
1017
|
+
close: () => Promise.resolve(),
|
|
1018
|
+
remove: () => Promise.reject(new DOMException('InvalidStateError', 'InvalidStateError')),
|
|
1019
|
+
addEventListener: () => {},
|
|
1020
|
+
removeEventListener: () => {},
|
|
1021
|
+
dispatchEvent: () => true
|
|
1022
|
+
};
|
|
1023
|
+
return sess;
|
|
1024
|
+
}
|
|
1025
|
+
};
|
|
1026
|
+
|
|
1027
|
+
const fakeMKSA = {
|
|
1028
|
+
keySystem: 'com.widevine.alpha',
|
|
1029
|
+
getConfiguration: () => resolvedCfg,
|
|
1030
|
+
createMediaKeys: () => Promise.resolve(fakeMKS)
|
|
1031
|
+
};
|
|
1032
|
+
|
|
1033
|
+
return Promise.resolve(fakeMKSA);
|
|
1034
|
+
}
|
|
1035
|
+
// All other key systems fall through to native
|
|
1036
|
+
try { return _origRMKSA(keySystem, configs); }
|
|
1037
|
+
catch (e) { return Promise.reject(e); }
|
|
1038
|
+
};
|
|
1039
|
+
|
|
1040
|
+
// Override on both Navigator.prototype and the instance
|
|
1041
|
+
try {
|
|
1042
|
+
Object.defineProperty(Navigator.prototype, 'requestMediaKeySystemAccess', {
|
|
1043
|
+
value: _fakeRMKSA, writable: true, configurable: true
|
|
1044
|
+
});
|
|
1045
|
+
} catch (e) {
|
|
1046
|
+
try { navigator.requestMediaKeySystemAccess = _fakeRMKSA; } catch (e2) {}
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
// Register for native-code toString masking
|
|
1050
|
+
const _s6 = typeof __stealth !== 'undefined' ? __stealth : {};
|
|
1051
|
+
if (_s6.utils) _s6.utils.registerNativeFunction(_fakeRMKSA, 'requestMediaKeySystemAccess');
|
|
1052
|
+
};
|
|
1053
|
+
|
|
925
1054
|
// Initialize all protections
|
|
926
1055
|
const DEBUG_PREFIX = '[CDP-FP-DEBUG]';
|
|
927
1056
|
const ERROR_PREFIX = '[CDP-FP-ERROR]';
|
|
928
|
-
|
|
1057
|
+
|
|
929
1058
|
console.log(DEBUG_PREFIX, 'Starting stealth protection injection...');
|
|
930
1059
|
|
|
931
1060
|
const applyProtection = (name, fn) => {
|
|
@@ -972,7 +1101,10 @@ export const createStealthScript = () => {
|
|
|
972
1101
|
applyProtection('Worker Constructor Protection', protectWorkerConstructor);
|
|
973
1102
|
applyProtection('SharedWorker Protection', protectSharedWorkerConstructor);
|
|
974
1103
|
applyProtection('PostMessage Protection', protectPostMessage);
|
|
975
|
-
|
|
1104
|
+
// Chrome authenticity patches — make Chromium look like real Chrome
|
|
1105
|
+
applyProtection('Document Visibility Spoofing', spoofDocumentVisibility);
|
|
1106
|
+
applyProtection('EME/Widevine Spoofing', spoofEME);
|
|
1107
|
+
|
|
976
1108
|
console.log(DEBUG_PREFIX, '✓ All stealth protections applied successfully');
|
|
977
1109
|
} catch (e) {
|
|
978
1110
|
console.error(ERROR_PREFIX, '✗ Failed to apply stealth protections:', e);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stealth-script.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/stealth-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAW,EAAE;IAC5C,OAAO
|
|
1
|
+
{"version":3,"file":"stealth-script.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/stealth-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAW,EAAE;IAC5C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA2kCL,CAAC;AACP,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-consistency.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/storage-consistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,8BAA8B,QAAO,
|
|
1
|
+
{"version":3,"file":"storage-consistency.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/storage-consistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,8BAA8B,QAAO,MA+UjD,CAAC"}
|
|
@@ -18,14 +18,16 @@ export const createStorageConsistencyScript = () => {
|
|
|
18
18
|
const spoofStorageAPIs = () => {
|
|
19
19
|
const platform = navigator.platform || 'Win32';
|
|
20
20
|
|
|
21
|
-
//
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
// Use centralized stable hash (set up by utils.ts before this module runs).
|
|
22
|
+
const _ss = typeof __stealth !== 'undefined' ? __stealth : {};
|
|
23
|
+
const sessionSeed = (_ss.stableHash
|
|
24
|
+
? _ss.stableHash(0xCAFE9002)
|
|
25
|
+
: (() => {
|
|
26
|
+
const ua = navigator.userAgent || '';
|
|
27
|
+
const s = window.screen;
|
|
28
|
+
return (ua.length * 17 + (s.width || 0) * 31 + (s.height || 0) * 13) % 1000000;
|
|
29
|
+
})()
|
|
30
|
+
);
|
|
29
31
|
|
|
30
32
|
// Seeded PRNG (mulberry32) for consistent values
|
|
31
33
|
const createSeededRNG = (seed) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage-consistency.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/storage-consistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAW,EAAE;IACvD,OAAO
|
|
1
|
+
{"version":3,"file":"storage-consistency.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/storage-consistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,CAAC,MAAM,8BAA8B,GAAG,GAAW,EAAE;IACvD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA6UL,CAAC;AACP,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timing-consistency.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/timing-consistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,6BAA6B,QAAO,
|
|
1
|
+
{"version":3,"file":"timing-consistency.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/timing-consistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,eAAO,MAAM,6BAA6B,QAAO,MA6PhD,CAAC"}
|
|
@@ -24,13 +24,15 @@ export const createTimingConsistencyScript = () => {
|
|
|
24
24
|
const originalDateNow = Date.now;
|
|
25
25
|
const originalPerformanceNow = performance.now.bind(performance);
|
|
26
26
|
|
|
27
|
-
//
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
// Use centralized stable hash (set up by utils.ts before this module runs).
|
|
28
|
+
const _ss = typeof __stealth !== 'undefined' ? __stealth : {};
|
|
29
|
+
const sessionSeed = (_ss.stableHash
|
|
30
|
+
? _ss.stableHash(0xCAFE9003)
|
|
31
|
+
: (() => {
|
|
32
|
+
const ua = navigator.userAgent || '';
|
|
33
|
+
return ua.length * 17 + (screen.width || 0) * 31;
|
|
34
|
+
})()
|
|
35
|
+
);
|
|
34
36
|
|
|
35
37
|
// Seeded PRNG (mulberry32) for consistent values
|
|
36
38
|
const seededRandom = (seed) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timing-consistency.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/timing-consistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAW,EAAE;IACtD,OAAO
|
|
1
|
+
{"version":3,"file":"timing-consistency.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/timing-consistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAW,EAAE;IACtD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA2PL,CAAC;AACP,CAAC,CAAC"}
|
|
@@ -132,24 +132,24 @@ export const createUAClientHintsSpoofingScript = (platform = 'Win32', generatedU
|
|
|
132
132
|
getHighEntropyValues: {
|
|
133
133
|
value: function(hints) {
|
|
134
134
|
return new Promise((resolve) => {
|
|
135
|
-
//
|
|
136
|
-
|
|
135
|
+
// Real Chrome resolves getHighEntropyValues via IPC microtask, not a random setTimeout
|
|
136
|
+
Promise.resolve().then(() => {
|
|
137
137
|
const result = {};
|
|
138
|
-
|
|
138
|
+
|
|
139
139
|
if (!hints || !Array.isArray(hints)) {
|
|
140
140
|
resolve(result);
|
|
141
141
|
return;
|
|
142
142
|
}
|
|
143
|
-
|
|
143
|
+
|
|
144
144
|
// Return requested hints
|
|
145
145
|
for (const hint of hints) {
|
|
146
146
|
if (hint in highEntropyValues) {
|
|
147
147
|
result[hint] = highEntropyValues[hint];
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
-
|
|
150
|
+
|
|
151
151
|
resolve(result);
|
|
152
|
-
}
|
|
152
|
+
});
|
|
153
153
|
});
|
|
154
154
|
},
|
|
155
155
|
writable: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,eAAO,MAAM,wBAAwB,QAAO,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,eAAO,MAAM,wBAAwB,QAAO,MAoiB3C,CAAC"}
|
|
@@ -491,7 +491,50 @@ export const createStealthUtilsScript = () => {
|
|
|
491
491
|
|
|
492
492
|
// Initialize toString patch immediately
|
|
493
493
|
patchToString();
|
|
494
|
-
|
|
494
|
+
|
|
495
|
+
// ============================================
|
|
496
|
+
// SHARED SEED UTILITIES
|
|
497
|
+
// Exposed via __stealth so all override modules
|
|
498
|
+
// use the same deterministic hash instead of
|
|
499
|
+
// duplicating _stableHash in every file.
|
|
500
|
+
// ============================================
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Deterministic hash that incorporates __stealth.seedKey + UA + screen.
|
|
504
|
+
* Every override module should call _s.stableHash(uniqueSalt) for its seed.
|
|
505
|
+
*/
|
|
506
|
+
const _stableHashFn = (salt) => {
|
|
507
|
+
const key = _s.seedKey || '';
|
|
508
|
+
const ua = (typeof navigator !== 'undefined' && navigator.userAgent) || '';
|
|
509
|
+
const sw = (typeof screen !== 'undefined' && screen.width) || 0;
|
|
510
|
+
const sh = (typeof screen !== 'undefined' && screen.height) || 0;
|
|
511
|
+
const cd = (typeof screen !== 'undefined' && screen.colorDepth) || 0;
|
|
512
|
+
let h = salt | 0;
|
|
513
|
+
for (let i = 0; i < key.length; i++) h = (h << 5) - h + key.charCodeAt(i) | 0;
|
|
514
|
+
for (let i = 0; i < ua.length; i++) h = (h << 5) - h + ua.charCodeAt(i) | 0;
|
|
515
|
+
h = (h << 5) - h + sw | 0;
|
|
516
|
+
h = (h << 5) - h + sh | 0;
|
|
517
|
+
h = (h << 5) - h + cd | 0;
|
|
518
|
+
return h >>> 0;
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Seeded PRNG factory (mulberry32).
|
|
523
|
+
* Usage: const rng = _s.createRNG(seed); rng() -> [0, 1)
|
|
524
|
+
*/
|
|
525
|
+
const _createRNGFn = (seed) => {
|
|
526
|
+
let s = seed | 0;
|
|
527
|
+
return () => {
|
|
528
|
+
s = s + 0x6D2B79F5 | 0;
|
|
529
|
+
let t = Math.imul(s ^ s >>> 15, 1 | s);
|
|
530
|
+
t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
|
|
531
|
+
return ((t ^ t >>> 14) >>> 0) / 4294967296;
|
|
532
|
+
};
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
_s.stableHash = _stableHashFn;
|
|
536
|
+
_s.createRNG = _createRNGFn;
|
|
537
|
+
|
|
495
538
|
// Export utilities via shared stealth store (not on window - avoids detection)
|
|
496
539
|
_s.utils = {
|
|
497
540
|
makeNativeString,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAW,EAAE;IACjD,OAAO
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAW,EAAE;IACjD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkiBV,CAAC;AACF,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webgl-spoofing.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgl-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,yBAAyB,sBAAuB,WAAW,KAAG,
|
|
1
|
+
{"version":3,"file":"webgl-spoofing.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgl-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,yBAAyB,sBAAuB,WAAW,KAAG,MAwQ1E,CAAC"}
|
|
@@ -109,7 +109,12 @@ export const createWebGLSpoofingScript = (fingerprintWebGL) => {
|
|
|
109
109
|
|
|
110
110
|
console.log('[CDP-FP-DEBUG] WebGL using platform:', platform, '- Vendor:', selectedVendor, 'Renderer:', selectedRenderer.substring(0, 60) + '...');
|
|
111
111
|
`}
|
|
112
|
-
|
|
112
|
+
|
|
113
|
+
// Store selected GPU info on __stealth for cross-API consistency (WebGPU reads this)
|
|
114
|
+
if (typeof __stealth !== 'undefined') {
|
|
115
|
+
__stealth.webglRenderer = selectedRenderer;
|
|
116
|
+
}
|
|
117
|
+
|
|
113
118
|
// Override getParameter
|
|
114
119
|
WebGLRenderingContext.prototype.getParameter = function(param) {
|
|
115
120
|
// UNMASKED_VENDOR_WEBGL
|
|
@@ -154,6 +159,43 @@ export const createWebGLSpoofingScript = (fingerprintWebGL) => {
|
|
|
154
159
|
};
|
|
155
160
|
}
|
|
156
161
|
|
|
162
|
+
// Override getShaderPrecisionFormat to prevent GPU cross-referencing.
|
|
163
|
+
// Anti-bot scripts can compare precision values against the claimed GPU/platform.
|
|
164
|
+
// These values match the standard IEEE 754 precision formats reported by modern
|
|
165
|
+
// D3D11/Metal/Vulkan drivers — consistent across NVIDIA, AMD, and Intel GPUs.
|
|
166
|
+
const _shaderPrecision = {
|
|
167
|
+
35633: { // VERTEX_SHADER
|
|
168
|
+
36336: { rangeMin: 1, rangeMax: 1, precision: 8 }, // LOW_FLOAT
|
|
169
|
+
36337: { rangeMin: 14, rangeMax: 14, precision: 10 }, // MEDIUM_FLOAT
|
|
170
|
+
36338: { rangeMin: 127, rangeMax: 127, precision: 23 }, // HIGH_FLOAT
|
|
171
|
+
36339: { rangeMin: 8, rangeMax: 7, precision: 0 }, // LOW_INT
|
|
172
|
+
36340: { rangeMin: 15, rangeMax: 14, precision: 0 }, // MEDIUM_INT
|
|
173
|
+
36341: { rangeMin: 31, rangeMax: 30, precision: 0 }, // HIGH_INT
|
|
174
|
+
},
|
|
175
|
+
35632: { // FRAGMENT_SHADER
|
|
176
|
+
36336: { rangeMin: 1, rangeMax: 1, precision: 8 },
|
|
177
|
+
36337: { rangeMin: 14, rangeMax: 14, precision: 10 },
|
|
178
|
+
36338: { rangeMin: 127, rangeMax: 127, precision: 23 },
|
|
179
|
+
36339: { rangeMin: 8, rangeMax: 7, precision: 0 },
|
|
180
|
+
36340: { rangeMin: 15, rangeMax: 14, precision: 0 },
|
|
181
|
+
36341: { rangeMin: 31, rangeMax: 30, precision: 0 },
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
const _origGetShaderPrecisionFormat = WebGLRenderingContext.prototype.getShaderPrecisionFormat;
|
|
185
|
+
WebGLRenderingContext.prototype.getShaderPrecisionFormat = function(shaderType, precisionType) {
|
|
186
|
+
const shaderFmts = _shaderPrecision[shaderType];
|
|
187
|
+
const fmt = shaderFmts && shaderFmts[precisionType];
|
|
188
|
+
if (fmt) {
|
|
189
|
+
// Return a plain object that mirrors WebGLShaderPrecisionFormat fields.
|
|
190
|
+
// Anti-bot scripts read .rangeMin/.rangeMax/.precision — instanceof is not checked.
|
|
191
|
+
return { rangeMin: fmt.rangeMin, rangeMax: fmt.rangeMax, precision: fmt.precision };
|
|
192
|
+
}
|
|
193
|
+
return _origGetShaderPrecisionFormat.apply(this, arguments);
|
|
194
|
+
};
|
|
195
|
+
if (typeof WebGL2RenderingContext !== 'undefined') {
|
|
196
|
+
WebGL2RenderingContext.prototype.getShaderPrecisionFormat = WebGLRenderingContext.prototype.getShaderPrecisionFormat;
|
|
197
|
+
}
|
|
198
|
+
|
|
157
199
|
// Override getSupportedExtensions with platform-appropriate extensions
|
|
158
200
|
const baseExtensions = [
|
|
159
201
|
'ANGLE_instanced_arrays', 'EXT_blend_minmax', 'EXT_color_buffer_half_float',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webgl-spoofing.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgl-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,gBAA8B,EAAU,EAAE;IAChF,iFAAiF;IACjF,MAAM,cAAc,GAAG,gBAAgB,IAAI,CAAC,gBAAgB,CAAC,cAAc,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAElH,OAAO;;;;;;;;;;UAUD,cAAc,CAAC,CAAC,CAAC;;oCAES,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;;;;SAI3D,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAuFH
|
|
1
|
+
{"version":3,"file":"webgl-spoofing.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgl-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,gBAA8B,EAAU,EAAE;IAChF,iFAAiF;IACjF,MAAM,cAAc,GAAG,gBAAgB,IAAI,CAAC,gBAAgB,CAAC,cAAc,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAElH,OAAO;;;;;;;;;;UAUD,cAAc,CAAC,CAAC,CAAC;;oCAES,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;;;;SAI3D,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAuFH;;;;;;;;;;;;;;;;;;;yBAmBgB,cAAc,IAAI,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,UAAU;;;yBAGxF,cAAc,IAAI,gBAAgB,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAgFjH,CAAC,cAAc,CAAC,CAAC,CAAC;;;;;;;;;SASnB,CAAC,CAAC,CAAC;;SAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA2CH,CAAC;AACP,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webgpu-spoofing.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgpu-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,0BAA0B,kCAA+B,
|
|
1
|
+
{"version":3,"file":"webgpu-spoofing.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgpu-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,0BAA0B,kCAA+B,MA0NrE,CAAC"}
|
|
@@ -64,7 +64,15 @@ export const createWebGPUSpoofingScript = (experimentalMode = false) => {
|
|
|
64
64
|
return new Proxy(adapter, {
|
|
65
65
|
get(adapterTarget, adapterProp) {
|
|
66
66
|
if (adapterProp === 'name') {
|
|
67
|
-
//
|
|
67
|
+
// Derive GPU name from WebGL renderer for cross-API consistency.
|
|
68
|
+
// webgl-spoofing.ts stores the selected renderer on __stealth.webglRenderer.
|
|
69
|
+
const _wglR = typeof __stealth !== 'undefined' && __stealth.webglRenderer;
|
|
70
|
+
if (_wglR) {
|
|
71
|
+
// Extract from "ANGLE (NVIDIA, NVIDIA GeForce RTX 4060 Direct3D11 ...)"
|
|
72
|
+
const _m = _wglR.match(/ANGLE \\(\\w+, ([^,]+?)(?:\\s+Direct3D|\\s+OpenGL|,)/);
|
|
73
|
+
if (_m) return _m[1].trim();
|
|
74
|
+
}
|
|
75
|
+
// Fallback: seeded pick from list
|
|
68
76
|
const gpuNames = [
|
|
69
77
|
'NVIDIA GeForce RTX 4060',
|
|
70
78
|
'NVIDIA GeForce RTX 3060',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webgpu-spoofing.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgpu-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,gBAAgB,GAAG,KAAK,EAAU,EAAE;IAC3E,OAAO;;;;;;;UAOD,gBAAgB,CAAC,CAAC,CAAC;;;;;;;;;SASpB,CAAC,CAAC,CAAC,EAAE
|
|
1
|
+
{"version":3,"file":"webgpu-spoofing.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgpu-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,gBAAgB,GAAG,KAAK,EAAU,EAAE;IAC3E,OAAO;;;;;;;UAOD,gBAAgB,CAAC,CAAC,CAAC;;;;;;;;;SASpB,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAwMR,CAAC;AACP,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webrtc-spoofing.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webrtc-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,0BAA0B,QAAO,
|
|
1
|
+
{"version":3,"file":"webrtc-spoofing.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webrtc-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,0BAA0B,QAAO,MA4M7C,CAAC;AAEF,eAAO,MAAM,yBAAyB,QAAO,MAgC5C,CAAC"}
|
|
@@ -159,9 +159,20 @@ export const createWebRTCSpoofingScript = () => {
|
|
|
159
159
|
if (cachedDeviceList) return Promise.resolve(cachedDeviceList);
|
|
160
160
|
|
|
161
161
|
return originalEnumerateDevices.apply(this, arguments).then(devices => {
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
162
|
+
// If the platform returns no devices (headless/server/CI), inject
|
|
163
|
+
// plausible fake devices so fingerprinters don't flag an empty list.
|
|
164
|
+
// A real desktop Chrome always has at least audioinput + audiooutput.
|
|
165
|
+
if (devices.length === 0) {
|
|
166
|
+
devices = [
|
|
167
|
+
{ kind: 'audioinput', label: '', deviceId: 'default', groupId: 'default' },
|
|
168
|
+
{ kind: 'audiooutput', label: '', deviceId: 'default', groupId: 'default' },
|
|
169
|
+
{ kind: 'audioinput', label: '', deviceId: '', groupId: '' },
|
|
170
|
+
{ kind: 'audiooutput', label: '', deviceId: '', groupId: '' },
|
|
171
|
+
];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Replace device IDs with deterministic session-keyed ones,
|
|
175
|
+
// keeping the real device count so repeated calls are consistent.
|
|
165
176
|
const groupIds = {};
|
|
166
177
|
cachedDeviceList = devices.map((device, index) => {
|
|
167
178
|
const groupKey = device.kind.replace(/input|output/, '');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webrtc-spoofing.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webrtc-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAW,EAAE;IACnD,OAAO
|
|
1
|
+
{"version":3,"file":"webrtc-spoofing.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webrtc-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAW,EAAE;IACnD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA0ML,CAAC;AACP,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAW,EAAE;IAClD,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA8BL,CAAC;AACP,CAAC,CAAC"}
|