jumpy-lion 0.0.41 → 0.0.43
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/dist/browser-controller.d.ts.map +1 -1
- package/dist/browser-controller.js +102 -16
- package/dist/browser-controller.js.map +1 -1
- package/dist/browser-plugin.d.ts +20 -1
- package/dist/browser-plugin.d.ts.map +1 -1
- package/dist/browser-plugin.js +21 -1
- package/dist/browser-plugin.js.map +1 -1
- package/dist/browser-process/browser.d.ts +22 -1
- package/dist/browser-process/browser.d.ts.map +1 -1
- package/dist/browser-process/browser.js +77 -5
- package/dist/browser-process/browser.js.map +1 -1
- package/dist/browser-profiles/chrome/default.d.ts +116 -0
- package/dist/browser-profiles/chrome/default.d.ts.map +1 -1
- package/dist/browser-profiles/chrome/default.js +118 -1
- package/dist/browser-profiles/chrome/default.js.map +1 -1
- package/dist/browser-profiles/chrome/populate-profile.d.ts +76 -0
- package/dist/browser-profiles/chrome/populate-profile.d.ts.map +1 -0
- package/dist/browser-profiles/chrome/populate-profile.js +300 -0
- package/dist/browser-profiles/chrome/populate-profile.js.map +1 -0
- package/dist/browser-profiles/index.d.ts +1 -0
- package/dist/browser-profiles/index.d.ts.map +1 -1
- package/dist/browser-profiles/index.js +2 -0
- package/dist/browser-profiles/index.js.map +1 -1
- package/dist/crawler.d.ts +32 -1
- package/dist/crawler.d.ts.map +1 -1
- package/dist/crawler.js +7 -0
- package/dist/crawler.js.map +1 -1
- package/dist/fingerprinting/custom-fingerprint-injector.d.ts +87 -0
- package/dist/fingerprinting/custom-fingerprint-injector.d.ts.map +1 -0
- package/dist/fingerprinting/custom-fingerprint-injector.js +342 -0
- package/dist/fingerprinting/custom-fingerprint-injector.js.map +1 -0
- package/dist/fingerprinting/fingerprint-injector.d.ts +40 -2
- package/dist/fingerprinting/fingerprint-injector.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-injector.js +452 -44
- 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 +11 -1
- package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/canvas-protection.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/canvas-protection.js +11 -1
- package/dist/fingerprinting/fingerprint-overrides/canvas-protection.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.d.ts +14 -0
- package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.js +776 -0
- package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.js +11 -1
- package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts +14 -0
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js +643 -0
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/font-spoofing.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/font-spoofing.js +11 -1
- package/dist/fingerprinting/fingerprint-overrides/font-spoofing.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/index.d.ts +17 -1
- package/dist/fingerprinting/fingerprint-overrides/index.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/index.js +21 -1
- package/dist/fingerprinting/fingerprint-overrides/index.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.d.ts +45 -0
- package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js +291 -0
- package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js +153 -90
- package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.js +4 -5
- package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.js +11 -1
- package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts +13 -0
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js +413 -70
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.d.ts +13 -0
- package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.js +355 -0
- package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.d.ts +12 -3
- package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.js +261 -71
- package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.d.ts +55 -0
- package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js +380 -0
- package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts +8 -0
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.js +756 -71
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/storage-consistency.d.ts +13 -0
- package/dist/fingerprinting/fingerprint-overrides/storage-consistency.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/storage-consistency.js +368 -0
- package/dist/fingerprinting/fingerprint-overrides/storage-consistency.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/timing-consistency.d.ts +13 -0
- package/dist/fingerprinting/fingerprint-overrides/timing-consistency.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/timing-consistency.js +438 -0
- package/dist/fingerprinting/fingerprint-overrides/timing-consistency.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts +7 -1
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.js +158 -58
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/utils.d.ts +12 -0
- package/dist/fingerprinting/fingerprint-overrides/utils.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/utils.js +517 -0
- package/dist/fingerprinting/fingerprint-overrides/utils.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js +51 -10
- 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 +11 -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 +11 -1
- package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js.map +1 -1
- package/dist/page.d.ts +12 -0
- package/dist/page.d.ts.map +1 -1
- package/dist/page.js +35 -3
- package/dist/page.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/dist/fingerprinting/canvas-fingerprint.d.ts +0 -4
- package/dist/fingerprinting/canvas-fingerprint.d.ts.map +0 -1
- package/dist/fingerprinting/canvas-fingerprint.js +0 -60
- package/dist/fingerprinting/canvas-fingerprint.js.map +0 -1
|
@@ -0,0 +1,776 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CDP Detection Bypass
|
|
3
|
+
* Comprehensive CDP and automation detection bypass for 2024-2025
|
|
4
|
+
*
|
|
5
|
+
* Handles:
|
|
6
|
+
* - Iframe contentWindow access hiding
|
|
7
|
+
* - Puppeteer/Playwright evaluation script traces
|
|
8
|
+
* - Error.captureStackTrace patching
|
|
9
|
+
* - Storage access API spoofing
|
|
10
|
+
* - SourceURL/SourceMap hiding
|
|
11
|
+
* - Chrome DevTools property removal
|
|
12
|
+
*/
|
|
13
|
+
export const createCDPDetectionBypassScript = () => {
|
|
14
|
+
return `
|
|
15
|
+
(() => {
|
|
16
|
+
'use strict';
|
|
17
|
+
|
|
18
|
+
// CDP Detection Bypass for 2025
|
|
19
|
+
const bypassCDPDetection = () => {
|
|
20
|
+
|
|
21
|
+
// 1. Remove Chrome DevTools / Selenium / Puppeteer specific properties
|
|
22
|
+
const removeAutomationProperties = () => {
|
|
23
|
+
const cdcProperties = Object.getOwnPropertyNames(window).filter(prop =>
|
|
24
|
+
prop.startsWith('cdc_') ||
|
|
25
|
+
prop.startsWith('$cdc_') ||
|
|
26
|
+
prop.includes('webdriver') ||
|
|
27
|
+
prop.includes('selenium') ||
|
|
28
|
+
prop.includes('puppeteer') ||
|
|
29
|
+
prop.includes('playwright')
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
cdcProperties.forEach(prop => {
|
|
33
|
+
try {
|
|
34
|
+
delete window[prop];
|
|
35
|
+
} catch (e) {
|
|
36
|
+
try {
|
|
37
|
+
Object.defineProperty(window, prop, {
|
|
38
|
+
get: () => undefined,
|
|
39
|
+
configurable: true
|
|
40
|
+
});
|
|
41
|
+
} catch (e2) {}
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Remove from document as well
|
|
46
|
+
const docProperties = Object.getOwnPropertyNames(document).filter(prop =>
|
|
47
|
+
prop.startsWith('$') ||
|
|
48
|
+
prop.includes('webdriver') ||
|
|
49
|
+
prop.includes('selenium')
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
docProperties.forEach(prop => {
|
|
53
|
+
try {
|
|
54
|
+
delete document[prop];
|
|
55
|
+
} catch (e) {}
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Cache parent window fingerprint values for cross-context consistency
|
|
60
|
+
const parentFingerprintCache = {
|
|
61
|
+
navigator: {
|
|
62
|
+
userAgent: navigator.userAgent,
|
|
63
|
+
platform: navigator.platform,
|
|
64
|
+
vendor: navigator.vendor,
|
|
65
|
+
language: navigator.language,
|
|
66
|
+
languages: navigator.languages ? [...navigator.languages] : ['en-US'],
|
|
67
|
+
hardwareConcurrency: navigator.hardwareConcurrency,
|
|
68
|
+
deviceMemory: navigator.deviceMemory,
|
|
69
|
+
maxTouchPoints: navigator.maxTouchPoints,
|
|
70
|
+
cookieEnabled: navigator.cookieEnabled,
|
|
71
|
+
onLine: navigator.onLine,
|
|
72
|
+
appVersion: navigator.appVersion,
|
|
73
|
+
appName: navigator.appName,
|
|
74
|
+
appCodeName: navigator.appCodeName,
|
|
75
|
+
product: navigator.product,
|
|
76
|
+
productSub: navigator.productSub,
|
|
77
|
+
vendorSub: navigator.vendorSub,
|
|
78
|
+
webdriver: false, // Always false
|
|
79
|
+
},
|
|
80
|
+
screen: {
|
|
81
|
+
width: screen.width,
|
|
82
|
+
height: screen.height,
|
|
83
|
+
availWidth: screen.availWidth,
|
|
84
|
+
availHeight: screen.availHeight,
|
|
85
|
+
colorDepth: screen.colorDepth,
|
|
86
|
+
pixelDepth: screen.pixelDepth,
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// 2. Override HTMLIFrameElement.prototype.contentWindow to hide CDP access AND ensure consistency
|
|
91
|
+
const protectIframeContentWindow = () => {
|
|
92
|
+
const originalContentWindowDescriptor = Object.getOwnPropertyDescriptor(
|
|
93
|
+
HTMLIFrameElement.prototype,
|
|
94
|
+
'contentWindow'
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
if (originalContentWindowDescriptor) {
|
|
98
|
+
Object.defineProperty(HTMLIFrameElement.prototype, 'contentWindow', {
|
|
99
|
+
get() {
|
|
100
|
+
const contentWindow = originalContentWindowDescriptor.get.call(this);
|
|
101
|
+
|
|
102
|
+
if (!contentWindow) return contentWindow;
|
|
103
|
+
|
|
104
|
+
// Check if the iframe is same-origin
|
|
105
|
+
try {
|
|
106
|
+
// Access a property to check if we have access
|
|
107
|
+
const _ = contentWindow.document;
|
|
108
|
+
|
|
109
|
+
// Create a navigator proxy that returns parent values for consistency
|
|
110
|
+
const createConsistentNavigatorProxy = (iframeNavigator) => {
|
|
111
|
+
return new Proxy(iframeNavigator, {
|
|
112
|
+
get(target, prop) {
|
|
113
|
+
// Return parent window values for fingerprint-sensitive properties
|
|
114
|
+
if (prop in parentFingerprintCache.navigator) {
|
|
115
|
+
return parentFingerprintCache.navigator[prop];
|
|
116
|
+
}
|
|
117
|
+
const value = target[prop];
|
|
118
|
+
if (typeof value === 'function') {
|
|
119
|
+
return value.bind(target);
|
|
120
|
+
}
|
|
121
|
+
return value;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Create a screen proxy that returns parent values
|
|
127
|
+
const createConsistentScreenProxy = (iframeScreen) => {
|
|
128
|
+
return new Proxy(iframeScreen, {
|
|
129
|
+
get(target, prop) {
|
|
130
|
+
if (prop in parentFingerprintCache.screen) {
|
|
131
|
+
return parentFingerprintCache.screen[prop];
|
|
132
|
+
}
|
|
133
|
+
const value = target[prop];
|
|
134
|
+
if (typeof value === 'function') {
|
|
135
|
+
return value.bind(target);
|
|
136
|
+
}
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
// If accessible, wrap it to hide automation traces AND ensure consistency
|
|
143
|
+
return new Proxy(contentWindow, {
|
|
144
|
+
get(target, prop) {
|
|
145
|
+
// Hide automation-related properties
|
|
146
|
+
if (prop === 'webdriver' ||
|
|
147
|
+
prop === '__webdriver_evaluate' ||
|
|
148
|
+
prop === '__selenium_evaluate' ||
|
|
149
|
+
prop === '__driver_evaluate' ||
|
|
150
|
+
prop === '__webdriver_script_function' ||
|
|
151
|
+
prop === '__webdriver_script_fn' ||
|
|
152
|
+
prop === '__fxdriver_evaluate' ||
|
|
153
|
+
prop === '__webdriver_unwrapped' ||
|
|
154
|
+
String(prop).startsWith('cdc_') ||
|
|
155
|
+
String(prop).startsWith('$cdc_')) {
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Return consistent navigator
|
|
160
|
+
if (prop === 'navigator') {
|
|
161
|
+
return createConsistentNavigatorProxy(target.navigator);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Return consistent screen
|
|
165
|
+
if (prop === 'screen') {
|
|
166
|
+
return createConsistentScreenProxy(target.screen);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const value = target[prop];
|
|
170
|
+
if (typeof value === 'function') {
|
|
171
|
+
return value.bind(target);
|
|
172
|
+
}
|
|
173
|
+
return value;
|
|
174
|
+
},
|
|
175
|
+
has(target, prop) {
|
|
176
|
+
if (String(prop).startsWith('cdc_') ||
|
|
177
|
+
String(prop).startsWith('$cdc_') ||
|
|
178
|
+
prop === 'webdriver') {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
return prop in target;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
} catch (e) {
|
|
185
|
+
// Cross-origin, return as-is
|
|
186
|
+
return contentWindow;
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
configurable: true,
|
|
190
|
+
enumerable: true
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
// 2b. Intercept iframe creation to ensure overrides apply to dynamically created iframes
|
|
196
|
+
const interceptIframeCreation = () => {
|
|
197
|
+
const originalCreateElement = document.createElement.bind(document);
|
|
198
|
+
|
|
199
|
+
document.createElement = function(tagName, options) {
|
|
200
|
+
const element = originalCreateElement(tagName, options);
|
|
201
|
+
|
|
202
|
+
if (tagName.toLowerCase() === 'iframe') {
|
|
203
|
+
// Monitor iframe load to apply overrides
|
|
204
|
+
element.addEventListener('load', function iframeLoadHandler() {
|
|
205
|
+
try {
|
|
206
|
+
const iframeWindow = element.contentWindow;
|
|
207
|
+
if (iframeWindow) {
|
|
208
|
+
// Apply automation property removal to iframe
|
|
209
|
+
const cdcProps = Object.getOwnPropertyNames(iframeWindow).filter(p =>
|
|
210
|
+
p.startsWith('cdc_') || p.startsWith('$cdc_') ||
|
|
211
|
+
p.includes('webdriver') || p.includes('selenium')
|
|
212
|
+
);
|
|
213
|
+
cdcProps.forEach(prop => {
|
|
214
|
+
try { delete iframeWindow[prop]; } catch (e) {}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Ensure navigator.webdriver is undefined in iframe
|
|
218
|
+
try {
|
|
219
|
+
Object.defineProperty(iframeWindow.navigator, 'webdriver', {
|
|
220
|
+
get: () => undefined,
|
|
221
|
+
configurable: true
|
|
222
|
+
});
|
|
223
|
+
} catch (e) {}
|
|
224
|
+
}
|
|
225
|
+
} catch (e) {
|
|
226
|
+
// Cross-origin iframe, cannot access
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return element;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// Make createElement look native
|
|
235
|
+
Object.defineProperty(document.createElement, 'toString', {
|
|
236
|
+
value: () => 'function createElement() { [native code] }',
|
|
237
|
+
configurable: false
|
|
238
|
+
});
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
// 3. Patch Error.captureStackTrace to hide automation stack frames
|
|
242
|
+
const patchErrorCaptureStackTrace = () => {
|
|
243
|
+
if (Error.captureStackTrace) {
|
|
244
|
+
const originalCaptureStackTrace = Error.captureStackTrace;
|
|
245
|
+
|
|
246
|
+
Error.captureStackTrace = function(targetObject, constructorOpt) {
|
|
247
|
+
originalCaptureStackTrace.call(this, targetObject, constructorOpt);
|
|
248
|
+
|
|
249
|
+
// Clean the stack trace of automation markers
|
|
250
|
+
if (targetObject.stack) {
|
|
251
|
+
const cleanStack = targetObject.stack
|
|
252
|
+
.split('\\n')
|
|
253
|
+
.filter(line => {
|
|
254
|
+
const lowerLine = line.toLowerCase();
|
|
255
|
+
return !lowerLine.includes('puppeteer') &&
|
|
256
|
+
!lowerLine.includes('playwright') &&
|
|
257
|
+
!lowerLine.includes('selenium') &&
|
|
258
|
+
!lowerLine.includes('webdriver') &&
|
|
259
|
+
!lowerLine.includes('__puppeteer_evaluation_script__') &&
|
|
260
|
+
!lowerLine.includes('__playwright_evaluation_script__') &&
|
|
261
|
+
!lowerLine.includes('evaluateonNewDocument') &&
|
|
262
|
+
!lowerLine.includes('pptr:') &&
|
|
263
|
+
!lowerLine.includes('devtools://');
|
|
264
|
+
})
|
|
265
|
+
.join('\\n');
|
|
266
|
+
|
|
267
|
+
Object.defineProperty(targetObject, 'stack', {
|
|
268
|
+
value: cleanStack,
|
|
269
|
+
writable: true,
|
|
270
|
+
configurable: true
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
// 4. Override Function constructor to hide sourceURL
|
|
278
|
+
const protectFunctionConstructor = () => {
|
|
279
|
+
const OriginalFunction = Function;
|
|
280
|
+
|
|
281
|
+
const FunctionProxy = new Proxy(OriginalFunction, {
|
|
282
|
+
construct(target, args) {
|
|
283
|
+
// Remove sourceURL comments from function body
|
|
284
|
+
if (args.length > 0) {
|
|
285
|
+
const lastArg = args[args.length - 1];
|
|
286
|
+
if (typeof lastArg === 'string') {
|
|
287
|
+
args[args.length - 1] = lastArg
|
|
288
|
+
.replace(/\\/\\/# sourceURL=[^\\n]*/g, '')
|
|
289
|
+
.replace(/\\/\\/# sourceMappingURL=[^\\n]*/g, '')
|
|
290
|
+
.replace(/__puppeteer_evaluation_script__/g, 'anonymous')
|
|
291
|
+
.replace(/__playwright_evaluation_script__/g, 'anonymous')
|
|
292
|
+
.replace(/pptr:[^\\n]*/g, '');
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return Reflect.construct(target, args);
|
|
297
|
+
},
|
|
298
|
+
apply(target, thisArg, args) {
|
|
299
|
+
if (args.length > 0) {
|
|
300
|
+
const lastArg = args[args.length - 1];
|
|
301
|
+
if (typeof lastArg === 'string') {
|
|
302
|
+
args[args.length - 1] = lastArg
|
|
303
|
+
.replace(/\\/\\/# sourceURL=[^\\n]*/g, '')
|
|
304
|
+
.replace(/\\/\\/# sourceMappingURL=[^\\n]*/g, '')
|
|
305
|
+
.replace(/__puppeteer_evaluation_script__/g, 'anonymous')
|
|
306
|
+
.replace(/__playwright_evaluation_script__/g, 'anonymous');
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return Reflect.apply(target, thisArg, args);
|
|
311
|
+
},
|
|
312
|
+
get(target, prop) {
|
|
313
|
+
// Return the original prototype when accessing .prototype
|
|
314
|
+
if (prop === 'prototype') {
|
|
315
|
+
return OriginalFunction.prototype;
|
|
316
|
+
}
|
|
317
|
+
return Reflect.get(target, prop);
|
|
318
|
+
},
|
|
319
|
+
set(target, prop, value) {
|
|
320
|
+
// Prevent setting prototype or other frozen properties
|
|
321
|
+
if (prop === 'prototype') {
|
|
322
|
+
return true; // Silently ignore
|
|
323
|
+
}
|
|
324
|
+
return Reflect.set(target, prop, value);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
// Use defineProperty to replace Function without modifying frozen prototype
|
|
329
|
+
try {
|
|
330
|
+
Object.defineProperty(window, 'Function', {
|
|
331
|
+
value: FunctionProxy,
|
|
332
|
+
writable: true,
|
|
333
|
+
enumerable: false,
|
|
334
|
+
configurable: true
|
|
335
|
+
});
|
|
336
|
+
} catch (e) {
|
|
337
|
+
// If we can't redefine, just assign
|
|
338
|
+
window.Function = FunctionProxy;
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
// 5. Override eval to hide sourceURL
|
|
343
|
+
const protectEval = () => {
|
|
344
|
+
const originalEval = window.eval;
|
|
345
|
+
|
|
346
|
+
window.eval = function(code) {
|
|
347
|
+
if (typeof code === 'string') {
|
|
348
|
+
code = code
|
|
349
|
+
.replace(/\\/\\/# sourceURL=[^\\n]*/g, '')
|
|
350
|
+
.replace(/\\/\\/# sourceMappingURL=[^\\n]*/g, '')
|
|
351
|
+
.replace(/__puppeteer_evaluation_script__/g, 'anonymous')
|
|
352
|
+
.replace(/__playwright_evaluation_script__/g, 'anonymous')
|
|
353
|
+
.replace(/pptr:[^)\\n]*/g, 'eval');
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return originalEval.call(this, code);
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
// Make eval look native
|
|
360
|
+
Object.defineProperty(window.eval, 'toString', {
|
|
361
|
+
value: function() { return 'function eval() { [native code] }'; },
|
|
362
|
+
configurable: false
|
|
363
|
+
});
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
// 6. Override document.hasStorageAccess for sandbox detection
|
|
367
|
+
const protectStorageAccess = () => {
|
|
368
|
+
if (document.hasStorageAccess) {
|
|
369
|
+
const originalHasStorageAccess = document.hasStorageAccess;
|
|
370
|
+
|
|
371
|
+
document.hasStorageAccess = function() {
|
|
372
|
+
// Always return a promise that resolves to true for same-origin
|
|
373
|
+
return Promise.resolve(true);
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
// Make it look native
|
|
377
|
+
Object.defineProperty(document.hasStorageAccess, 'toString', {
|
|
378
|
+
value: function() { return 'function hasStorageAccess() { [native code] }'; }
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (document.requestStorageAccess) {
|
|
383
|
+
document.requestStorageAccess = function() {
|
|
384
|
+
return Promise.resolve();
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
// 7. Protect window.name from automation markers
|
|
390
|
+
const protectWindowName = () => {
|
|
391
|
+
let windowName = window.name;
|
|
392
|
+
|
|
393
|
+
Object.defineProperty(window, 'name', {
|
|
394
|
+
get() {
|
|
395
|
+
// Filter out automation-related markers from window name
|
|
396
|
+
if (windowName && typeof windowName === 'string') {
|
|
397
|
+
if (windowName.includes('puppeteer') ||
|
|
398
|
+
windowName.includes('playwright') ||
|
|
399
|
+
windowName.includes('selenium') ||
|
|
400
|
+
windowName.includes('webdriver')) {
|
|
401
|
+
return '';
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
return windowName;
|
|
405
|
+
},
|
|
406
|
+
set(value) {
|
|
407
|
+
windowName = value;
|
|
408
|
+
},
|
|
409
|
+
configurable: true,
|
|
410
|
+
enumerable: true
|
|
411
|
+
});
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
// 8. Override Object.getOwnPropertyDescriptor to hide automation properties
|
|
415
|
+
// AND make overridden properties appear native (configurable: false)
|
|
416
|
+
const protectPropertyDescriptor = () => {
|
|
417
|
+
const originalGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
418
|
+
|
|
419
|
+
// Properties that should appear as native (configurable: false)
|
|
420
|
+
const nativeNavigatorProps = new Set([
|
|
421
|
+
'userAgent', 'platform', 'vendor', 'vendorSub', 'productSub',
|
|
422
|
+
'hardwareConcurrency', 'deviceMemory', 'maxTouchPoints',
|
|
423
|
+
'language', 'languages', 'cookieEnabled', 'onLine', 'webdriver',
|
|
424
|
+
'plugins', 'mimeTypes', 'userAgentData', 'connection',
|
|
425
|
+
'pdfViewerEnabled', 'doNotTrack', 'appCodeName', 'appName',
|
|
426
|
+
'appVersion', 'product', 'oscpu'
|
|
427
|
+
]);
|
|
428
|
+
|
|
429
|
+
const nativeScreenProps = new Set([
|
|
430
|
+
'width', 'height', 'availWidth', 'availHeight', 'colorDepth',
|
|
431
|
+
'pixelDepth', 'availLeft', 'availTop', 'orientation'
|
|
432
|
+
]);
|
|
433
|
+
|
|
434
|
+
const nativeWindowProps = new Set([
|
|
435
|
+
'devicePixelRatio', 'innerWidth', 'innerHeight', 'outerWidth',
|
|
436
|
+
'outerHeight', 'screenX', 'screenY', 'screenLeft', 'screenTop'
|
|
437
|
+
]);
|
|
438
|
+
|
|
439
|
+
Object.getOwnPropertyDescriptor = function(obj, prop) {
|
|
440
|
+
// Hide automation-related properties
|
|
441
|
+
if (obj === navigator && prop === 'webdriver') {
|
|
442
|
+
return undefined;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (typeof prop === 'string' &&
|
|
446
|
+
(prop.startsWith('cdc_') ||
|
|
447
|
+
prop.startsWith('$cdc_') ||
|
|
448
|
+
prop.includes('__webdriver') ||
|
|
449
|
+
prop.includes('__selenium') ||
|
|
450
|
+
prop.includes('__puppeteer') ||
|
|
451
|
+
prop.includes('__playwright'))) {
|
|
452
|
+
return undefined;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Get the real descriptor
|
|
456
|
+
const descriptor = originalGetOwnPropertyDescriptor.call(this, obj, prop);
|
|
457
|
+
|
|
458
|
+
if (!descriptor) return descriptor;
|
|
459
|
+
|
|
460
|
+
// Make navigator properties appear native
|
|
461
|
+
if (obj === navigator && nativeNavigatorProps.has(prop)) {
|
|
462
|
+
return {
|
|
463
|
+
...descriptor,
|
|
464
|
+
configurable: false,
|
|
465
|
+
enumerable: true
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Make screen properties appear native
|
|
470
|
+
if (obj === screen && nativeScreenProps.has(prop)) {
|
|
471
|
+
return {
|
|
472
|
+
...descriptor,
|
|
473
|
+
configurable: false,
|
|
474
|
+
enumerable: true
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// Make window properties appear native
|
|
479
|
+
if (obj === window && nativeWindowProps.has(prop)) {
|
|
480
|
+
return {
|
|
481
|
+
...descriptor,
|
|
482
|
+
configurable: false,
|
|
483
|
+
enumerable: true
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Check prototype integrity module for fake descriptors
|
|
488
|
+
if (window.__prototypeIntegrity__) {
|
|
489
|
+
const protoIntegrity = window.__prototypeIntegrity__;
|
|
490
|
+
if (protoIntegrity.isOverridden && protoIntegrity.isOverridden(obj, prop)) {
|
|
491
|
+
const fakeDesc = protoIntegrity.createNativeDescriptor(obj, prop, descriptor);
|
|
492
|
+
if (fakeDesc) return fakeDesc;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
return descriptor;
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
// Also patch Reflect.getOwnPropertyDescriptor
|
|
500
|
+
if (typeof Reflect !== 'undefined' && Reflect.getOwnPropertyDescriptor) {
|
|
501
|
+
const originalReflectGetOwnPropertyDescriptor = Reflect.getOwnPropertyDescriptor;
|
|
502
|
+
|
|
503
|
+
Reflect.getOwnPropertyDescriptor = function(obj, prop) {
|
|
504
|
+
// Use our patched Object.getOwnPropertyDescriptor
|
|
505
|
+
return Object.getOwnPropertyDescriptor(obj, prop);
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
// 8b. Protect Object.getPrototypeOf from revealing automation
|
|
511
|
+
const protectGetPrototypeOf = () => {
|
|
512
|
+
const originalGetPrototypeOf = Object.getPrototypeOf;
|
|
513
|
+
const originalReflectGetPrototypeOf = typeof Reflect !== 'undefined' ? Reflect.getPrototypeOf : null;
|
|
514
|
+
|
|
515
|
+
// Cache expected prototypes
|
|
516
|
+
const expectedPrototypes = new Map();
|
|
517
|
+
expectedPrototypes.set(navigator, Navigator.prototype);
|
|
518
|
+
expectedPrototypes.set(screen, Screen.prototype);
|
|
519
|
+
expectedPrototypes.set(window, Window.prototype);
|
|
520
|
+
expectedPrototypes.set(document, HTMLDocument.prototype);
|
|
521
|
+
|
|
522
|
+
Object.getPrototypeOf = function(obj) {
|
|
523
|
+
const proto = originalGetPrototypeOf.call(this, obj);
|
|
524
|
+
|
|
525
|
+
// Ensure navigator returns Navigator.prototype
|
|
526
|
+
if (obj === navigator) {
|
|
527
|
+
return Navigator.prototype;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Ensure screen returns Screen.prototype
|
|
531
|
+
if (obj === screen) {
|
|
532
|
+
return Screen.prototype;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
return proto;
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
if (originalReflectGetPrototypeOf) {
|
|
539
|
+
Reflect.getPrototypeOf = function(obj) {
|
|
540
|
+
return Object.getPrototypeOf(obj);
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
// 9. Override Object.getOwnPropertyNames to hide automation properties
|
|
546
|
+
const protectPropertyNames = () => {
|
|
547
|
+
const originalGetOwnPropertyNames = Object.getOwnPropertyNames;
|
|
548
|
+
|
|
549
|
+
Object.getOwnPropertyNames = function(obj) {
|
|
550
|
+
const names = originalGetOwnPropertyNames.call(this, obj);
|
|
551
|
+
|
|
552
|
+
return names.filter(name => {
|
|
553
|
+
const lowerName = name.toLowerCase();
|
|
554
|
+
return !name.startsWith('cdc_') &&
|
|
555
|
+
!name.startsWith('$cdc_') &&
|
|
556
|
+
!lowerName.includes('webdriver') &&
|
|
557
|
+
!lowerName.includes('selenium') &&
|
|
558
|
+
!lowerName.includes('puppeteer') &&
|
|
559
|
+
!lowerName.includes('playwright') &&
|
|
560
|
+
!name.startsWith('__driver') &&
|
|
561
|
+
!name.startsWith('__selenium') &&
|
|
562
|
+
!name.startsWith('__webdriver');
|
|
563
|
+
});
|
|
564
|
+
};
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
// 10. Override Object.keys similarly
|
|
568
|
+
const protectObjectKeys = () => {
|
|
569
|
+
const originalKeys = Object.keys;
|
|
570
|
+
|
|
571
|
+
Object.keys = function(obj) {
|
|
572
|
+
const keys = originalKeys.call(this, obj);
|
|
573
|
+
|
|
574
|
+
return keys.filter(key => {
|
|
575
|
+
const lowerKey = key.toLowerCase();
|
|
576
|
+
return !key.startsWith('cdc_') &&
|
|
577
|
+
!key.startsWith('$cdc_') &&
|
|
578
|
+
!lowerKey.includes('webdriver') &&
|
|
579
|
+
!lowerKey.includes('selenium') &&
|
|
580
|
+
!lowerKey.includes('puppeteer');
|
|
581
|
+
});
|
|
582
|
+
};
|
|
583
|
+
};
|
|
584
|
+
|
|
585
|
+
// 11. Protect against Reflect.ownKeys detection
|
|
586
|
+
const protectReflectOwnKeys = () => {
|
|
587
|
+
const originalOwnKeys = Reflect.ownKeys;
|
|
588
|
+
|
|
589
|
+
Reflect.ownKeys = function(obj) {
|
|
590
|
+
const keys = originalOwnKeys.call(this, obj);
|
|
591
|
+
|
|
592
|
+
return keys.filter(key => {
|
|
593
|
+
const keyStr = String(key).toLowerCase();
|
|
594
|
+
return !keyStr.startsWith('cdc_') &&
|
|
595
|
+
!keyStr.startsWith('$cdc_') &&
|
|
596
|
+
!keyStr.includes('webdriver') &&
|
|
597
|
+
!keyStr.includes('selenium') &&
|
|
598
|
+
!keyStr.includes('puppeteer');
|
|
599
|
+
});
|
|
600
|
+
};
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
// 12. Protect navigator.permissions.query for automation detection
|
|
604
|
+
const protectPermissionsQuery = () => {
|
|
605
|
+
if (navigator.permissions && navigator.permissions.query) {
|
|
606
|
+
const originalQuery = navigator.permissions.query;
|
|
607
|
+
|
|
608
|
+
navigator.permissions.query = function(descriptor) {
|
|
609
|
+
// Handle notifications permission specifically
|
|
610
|
+
if (descriptor && descriptor.name === 'notifications') {
|
|
611
|
+
return Promise.resolve({
|
|
612
|
+
state: 'prompt',
|
|
613
|
+
name: 'notifications',
|
|
614
|
+
onchange: null,
|
|
615
|
+
addEventListener: () => {},
|
|
616
|
+
removeEventListener: () => {},
|
|
617
|
+
dispatchEvent: () => true
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
return originalQuery.apply(this, arguments);
|
|
622
|
+
};
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
// 13. Protect MediaSession API
|
|
627
|
+
const protectMediaSession = () => {
|
|
628
|
+
if (navigator.mediaSession) {
|
|
629
|
+
// Ensure mediaSession appears properly configured
|
|
630
|
+
try {
|
|
631
|
+
Object.defineProperty(navigator.mediaSession, 'playbackState', {
|
|
632
|
+
get: () => 'none',
|
|
633
|
+
configurable: true
|
|
634
|
+
});
|
|
635
|
+
} catch (e) {}
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
// 14. Protect against CDP Runtime detection via timing
|
|
640
|
+
const protectRuntimeTiming = () => {
|
|
641
|
+
// Detect CDP calls that happen synchronously
|
|
642
|
+
const originalDateNow = Date.now;
|
|
643
|
+
let lastCallTime = 0;
|
|
644
|
+
|
|
645
|
+
Date.now = function() {
|
|
646
|
+
const now = originalDateNow.call(this);
|
|
647
|
+
|
|
648
|
+
// Ensure minimum 1ms between calls to appear human
|
|
649
|
+
if (now - lastCallTime < 1) {
|
|
650
|
+
lastCallTime = now + 1;
|
|
651
|
+
return lastCallTime;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
lastCallTime = now;
|
|
655
|
+
return now;
|
|
656
|
+
};
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
// 15. Protect native constructor toString (DataDome checks these)
|
|
660
|
+
const protectConstructorToString = () => {
|
|
661
|
+
// List of constructors that DataDome checks
|
|
662
|
+
const constructorsToProtect = [
|
|
663
|
+
{ name: 'CompressionStream', ctor: typeof CompressionStream !== 'undefined' ? CompressionStream : null },
|
|
664
|
+
{ name: 'MutationObserver', ctor: typeof MutationObserver !== 'undefined' ? MutationObserver : null },
|
|
665
|
+
{ name: 'Date', ctor: Date },
|
|
666
|
+
{ name: 'Worker', ctor: typeof Worker !== 'undefined' ? Worker : null },
|
|
667
|
+
{ name: 'Error', ctor: Error },
|
|
668
|
+
{ name: 'Promise', ctor: Promise },
|
|
669
|
+
{ name: 'Proxy', ctor: typeof Proxy !== 'undefined' ? Proxy : null },
|
|
670
|
+
{ name: 'Reflect', ctor: typeof Reflect !== 'undefined' ? Reflect : null },
|
|
671
|
+
{ name: 'Map', ctor: Map },
|
|
672
|
+
{ name: 'Set', ctor: Set },
|
|
673
|
+
{ name: 'WeakMap', ctor: WeakMap },
|
|
674
|
+
{ name: 'WeakSet', ctor: WeakSet },
|
|
675
|
+
{ name: 'Symbol', ctor: Symbol },
|
|
676
|
+
{ name: 'ArrayBuffer', ctor: ArrayBuffer },
|
|
677
|
+
{ name: 'DataView', ctor: DataView },
|
|
678
|
+
{ name: 'Intl', ctor: typeof Intl !== 'undefined' ? Intl : null }
|
|
679
|
+
];
|
|
680
|
+
|
|
681
|
+
constructorsToProtect.forEach(({ name, ctor }) => {
|
|
682
|
+
if (!ctor) return;
|
|
683
|
+
|
|
684
|
+
try {
|
|
685
|
+
// Make the constructor's toString return native code
|
|
686
|
+
const nativeString = \`function \${name}() { [native code] }\`;
|
|
687
|
+
|
|
688
|
+
Object.defineProperty(ctor, 'toString', {
|
|
689
|
+
value: function() { return nativeString; },
|
|
690
|
+
writable: true,
|
|
691
|
+
configurable: true
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
// Also protect the prototype.constructor if it exists
|
|
695
|
+
if (ctor.prototype && ctor.prototype.constructor) {
|
|
696
|
+
Object.defineProperty(ctor.prototype.constructor, 'toString', {
|
|
697
|
+
value: function() { return nativeString; },
|
|
698
|
+
writable: true,
|
|
699
|
+
configurable: true
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
} catch (e) {
|
|
703
|
+
// Some constructors may be frozen, skip them
|
|
704
|
+
}
|
|
705
|
+
});
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
// 16. Clean up any existing automation markers in the DOM
|
|
709
|
+
const cleanDOMAutomationMarkers = () => {
|
|
710
|
+
// Remove data attributes that might indicate automation
|
|
711
|
+
const elements = document.querySelectorAll('[data-webdriver], [data-selenium], [data-puppeteer]');
|
|
712
|
+
elements.forEach(el => {
|
|
713
|
+
el.removeAttribute('data-webdriver');
|
|
714
|
+
el.removeAttribute('data-selenium');
|
|
715
|
+
el.removeAttribute('data-puppeteer');
|
|
716
|
+
});
|
|
717
|
+
|
|
718
|
+
// Clean script tags with automation-related src
|
|
719
|
+
const scripts = document.querySelectorAll('script');
|
|
720
|
+
scripts.forEach(script => {
|
|
721
|
+
if (script.src && (
|
|
722
|
+
script.src.includes('puppeteer') ||
|
|
723
|
+
script.src.includes('playwright') ||
|
|
724
|
+
script.src.includes('selenium')
|
|
725
|
+
)) {
|
|
726
|
+
script.remove();
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
};
|
|
730
|
+
|
|
731
|
+
// Initialize all protections
|
|
732
|
+
try {
|
|
733
|
+
removeAutomationProperties();
|
|
734
|
+
protectIframeContentWindow();
|
|
735
|
+
interceptIframeCreation(); // Ensure dynamic iframes get overrides
|
|
736
|
+
patchErrorCaptureStackTrace();
|
|
737
|
+
protectFunctionConstructor();
|
|
738
|
+
protectEval();
|
|
739
|
+
protectStorageAccess();
|
|
740
|
+
protectWindowName();
|
|
741
|
+
protectPropertyDescriptor();
|
|
742
|
+
protectGetPrototypeOf(); // NEW: Protect Object.getPrototypeOf
|
|
743
|
+
protectPropertyNames();
|
|
744
|
+
protectObjectKeys();
|
|
745
|
+
protectReflectOwnKeys();
|
|
746
|
+
protectPermissionsQuery();
|
|
747
|
+
protectMediaSession();
|
|
748
|
+
protectRuntimeTiming();
|
|
749
|
+
protectConstructorToString(); // DataDome checks constructor.toString()
|
|
750
|
+
|
|
751
|
+
// Clean DOM after a short delay to catch dynamically added elements
|
|
752
|
+
if (document.readyState === 'loading') {
|
|
753
|
+
document.addEventListener('DOMContentLoaded', cleanDOMAutomationMarkers);
|
|
754
|
+
} else {
|
|
755
|
+
cleanDOMAutomationMarkers();
|
|
756
|
+
}
|
|
757
|
+
} catch (e) {
|
|
758
|
+
console.error('[CDP-DETECTION-BYPASS] Failed to apply CDP detection bypass:', e);
|
|
759
|
+
throw e; // Rethrow to make errors visible
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
|
|
763
|
+
const DEBUG_PREFIX = '[CDP-FP-DEBUG]';
|
|
764
|
+
const ERROR_PREFIX = '[CDP-FP-ERROR]';
|
|
765
|
+
|
|
766
|
+
try {
|
|
767
|
+
console.log(DEBUG_PREFIX, 'Starting CDP detection bypass...');
|
|
768
|
+
bypassCDPDetection();
|
|
769
|
+
console.log(DEBUG_PREFIX, '✓ CDP detection bypass applied');
|
|
770
|
+
} catch (e) {
|
|
771
|
+
console.error(ERROR_PREFIX, '✗ Failed to apply CDP detection bypass:', e);
|
|
772
|
+
throw e;
|
|
773
|
+
}
|
|
774
|
+
})();`;
|
|
775
|
+
};
|
|
776
|
+
//# sourceMappingURL=cdp-detection-bypass.js.map
|