jumpy-lion 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/dist/browser-controller.d.ts +22 -3
  2. package/dist/browser-controller.d.ts.map +1 -1
  3. package/dist/browser-controller.js +316 -71
  4. package/dist/browser-controller.js.map +1 -1
  5. package/dist/browser-plugin.d.ts +56 -7
  6. package/dist/browser-plugin.d.ts.map +1 -1
  7. package/dist/browser-plugin.js +268 -56
  8. package/dist/browser-plugin.js.map +1 -1
  9. package/dist/browser-process/browser.d.ts +39 -0
  10. package/dist/browser-process/browser.d.ts.map +1 -1
  11. package/dist/browser-process/browser.js +125 -16
  12. package/dist/browser-process/browser.js.map +1 -1
  13. package/dist/browser-process/process.d.ts +9 -0
  14. package/dist/browser-process/process.d.ts.map +1 -1
  15. package/dist/browser-process/process.js +100 -6
  16. package/dist/browser-process/process.js.map +1 -1
  17. package/dist/browser-profiles/chrome/default.d.ts +116 -0
  18. package/dist/browser-profiles/chrome/default.d.ts.map +1 -1
  19. package/dist/browser-profiles/chrome/default.js +118 -1
  20. package/dist/browser-profiles/chrome/default.js.map +1 -1
  21. package/dist/browser-profiles/chrome/populate-profile.d.ts +76 -0
  22. package/dist/browser-profiles/chrome/populate-profile.d.ts.map +1 -0
  23. package/dist/browser-profiles/chrome/populate-profile.js +300 -0
  24. package/dist/browser-profiles/chrome/populate-profile.js.map +1 -0
  25. package/dist/browser-profiles/index.d.ts +1 -0
  26. package/dist/browser-profiles/index.d.ts.map +1 -1
  27. package/dist/browser-profiles/index.js +2 -0
  28. package/dist/browser-profiles/index.js.map +1 -1
  29. package/dist/crawler.d.ts +81 -9
  30. package/dist/crawler.d.ts.map +1 -1
  31. package/dist/crawler.js +26 -10
  32. package/dist/crawler.js.map +1 -1
  33. package/dist/fingerprinting/all-fingerprint-defender/_locales/en/messages.json +95 -0
  34. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-16ff15da.d.ts +2 -0
  35. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-16ff15da.d.ts.map +1 -0
  36. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-16ff15da.js +1 -0
  37. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-16ff15da.js.map +1 -0
  38. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-1a1456ec.d.ts +2 -0
  39. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-1a1456ec.d.ts.map +1 -0
  40. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-1a1456ec.js +1 -0
  41. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-1a1456ec.js.map +1 -0
  42. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-3a7b59dd.d.ts +83 -0
  43. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-3a7b59dd.d.ts.map +1 -0
  44. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-3a7b59dd.js +1 -0
  45. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-3a7b59dd.js.map +1 -0
  46. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-7ce85519.d.ts +2 -0
  47. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-7ce85519.d.ts.map +1 -0
  48. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-7ce85519.js +1 -0
  49. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-7ce85519.js.map +1 -0
  50. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-aaea1190.d.ts +2 -0
  51. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-aaea1190.d.ts.map +1 -0
  52. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-aaea1190.js +1 -0
  53. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-aaea1190.js.map +1 -0
  54. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-b4410958.d.ts +2 -0
  55. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-b4410958.d.ts.map +1 -0
  56. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-b4410958.js +1 -0
  57. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-b4410958.js.map +1 -0
  58. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-dfed3562.d.ts +2 -0
  59. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-dfed3562.d.ts.map +1 -0
  60. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-dfed3562.js +1 -0
  61. package/dist/fingerprinting/all-fingerprint-defender/assets/chunk-dfed3562.js.map +1 -0
  62. package/dist/fingerprinting/all-fingerprint-defender/assets/debounce-09920c81.css +1 -0
  63. package/dist/fingerprinting/all-fingerprint-defender/assets/options-fe2fb5aa.css +1 -0
  64. package/dist/fingerprinting/all-fingerprint-defender/assets/popup-1886d2ef.css +1 -0
  65. package/dist/fingerprinting/all-fingerprint-defender/img/icon-128.png +0 -0
  66. package/dist/fingerprinting/all-fingerprint-defender/img/icon-16.png +0 -0
  67. package/dist/fingerprinting/all-fingerprint-defender/img/icon-24.png +0 -0
  68. package/dist/fingerprinting/all-fingerprint-defender/img/icon-32-disabled.png +0 -0
  69. package/dist/fingerprinting/all-fingerprint-defender/img/icon-32.png +0 -0
  70. package/dist/fingerprinting/all-fingerprint-defender/img/icon-48.png +0 -0
  71. package/dist/fingerprinting/all-fingerprint-defender/manifest.json +83 -0
  72. package/dist/fingerprinting/all-fingerprint-defender/options.html +17 -0
  73. package/dist/fingerprinting/all-fingerprint-defender/popup.html +23 -0
  74. package/dist/fingerprinting/anti-webgpu/background.d.ts +2 -0
  75. package/dist/fingerprinting/anti-webgpu/background.d.ts.map +1 -0
  76. package/dist/fingerprinting/anti-webgpu/background.js +4 -0
  77. package/dist/fingerprinting/anti-webgpu/background.js.map +1 -0
  78. package/dist/fingerprinting/anti-webgpu/data/content_script/inject.d.ts +2 -0
  79. package/dist/fingerprinting/anti-webgpu/data/content_script/inject.d.ts.map +1 -0
  80. package/dist/fingerprinting/anti-webgpu/data/content_script/inject.js +50 -0
  81. package/dist/fingerprinting/anti-webgpu/data/content_script/inject.js.map +1 -0
  82. package/dist/fingerprinting/anti-webgpu/data/content_script/page_context/inject.d.ts +2 -0
  83. package/dist/fingerprinting/anti-webgpu/data/content_script/page_context/inject.d.ts.map +1 -0
  84. package/dist/fingerprinting/anti-webgpu/data/content_script/page_context/inject.js +172 -0
  85. package/dist/fingerprinting/anti-webgpu/data/content_script/page_context/inject.js.map +1 -0
  86. package/dist/fingerprinting/anti-webgpu/data/icons/128.png +0 -0
  87. package/dist/fingerprinting/anti-webgpu/data/icons/16.png +0 -0
  88. package/dist/fingerprinting/anti-webgpu/data/icons/32.png +0 -0
  89. package/dist/fingerprinting/anti-webgpu/data/icons/48.png +0 -0
  90. package/dist/fingerprinting/anti-webgpu/data/icons/64.png +0 -0
  91. package/dist/fingerprinting/anti-webgpu/data/popup/popup.css +88 -0
  92. package/dist/fingerprinting/anti-webgpu/data/popup/popup.d.ts +2 -0
  93. package/dist/fingerprinting/anti-webgpu/data/popup/popup.d.ts.map +1 -0
  94. package/dist/fingerprinting/anti-webgpu/data/popup/popup.html +58 -0
  95. package/dist/fingerprinting/anti-webgpu/data/popup/popup.js +96 -0
  96. package/dist/fingerprinting/anti-webgpu/data/popup/popup.js.map +1 -0
  97. package/dist/fingerprinting/anti-webgpu/lib/chrome.d.ts +2 -0
  98. package/dist/fingerprinting/anti-webgpu/lib/chrome.d.ts.map +1 -0
  99. package/dist/fingerprinting/anti-webgpu/lib/chrome.js +249 -0
  100. package/dist/fingerprinting/anti-webgpu/lib/chrome.js.map +1 -0
  101. package/dist/fingerprinting/anti-webgpu/lib/common.d.ts +2 -0
  102. package/dist/fingerprinting/anti-webgpu/lib/common.d.ts.map +1 -0
  103. package/dist/fingerprinting/anti-webgpu/lib/common.js +86 -0
  104. package/dist/fingerprinting/anti-webgpu/lib/common.js.map +1 -0
  105. package/dist/fingerprinting/anti-webgpu/lib/config.d.ts +2 -0
  106. package/dist/fingerprinting/anti-webgpu/lib/config.d.ts.map +1 -0
  107. package/dist/fingerprinting/anti-webgpu/lib/config.js +14 -0
  108. package/dist/fingerprinting/anti-webgpu/lib/config.js.map +1 -0
  109. package/dist/fingerprinting/anti-webgpu/lib/runtime.d.ts +2 -0
  110. package/dist/fingerprinting/anti-webgpu/lib/runtime.d.ts.map +1 -0
  111. package/dist/fingerprinting/anti-webgpu/lib/runtime.js +107 -0
  112. package/dist/fingerprinting/anti-webgpu/lib/runtime.js.map +1 -0
  113. package/dist/fingerprinting/anti-webgpu/manifest.json +58 -0
  114. package/dist/fingerprinting/custom-fingerprint-injector.d.ts +87 -0
  115. package/dist/fingerprinting/custom-fingerprint-injector.d.ts.map +1 -0
  116. package/dist/fingerprinting/custom-fingerprint-injector.js +342 -0
  117. package/dist/fingerprinting/custom-fingerprint-injector.js.map +1 -0
  118. package/dist/fingerprinting/fingerprint-injector.d.ts +157 -0
  119. package/dist/fingerprinting/fingerprint-injector.d.ts.map +1 -0
  120. package/dist/fingerprinting/fingerprint-injector.js +632 -0
  121. package/dist/fingerprinting/fingerprint-injector.js.map +1 -0
  122. package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.d.ts +6 -0
  123. package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.d.ts.map +1 -0
  124. package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.js +119 -0
  125. package/dist/fingerprinting/fingerprint-overrides/audio-spoofing.js.map +1 -0
  126. package/dist/fingerprinting/fingerprint-overrides/canvas-protection.d.ts +6 -0
  127. package/dist/fingerprinting/fingerprint-overrides/canvas-protection.d.ts.map +1 -0
  128. package/dist/fingerprinting/fingerprint-overrides/canvas-protection.js +149 -0
  129. package/dist/fingerprinting/fingerprint-overrides/canvas-protection.js.map +1 -0
  130. package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.d.ts +14 -0
  131. package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.d.ts.map +1 -0
  132. package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.js +763 -0
  133. package/dist/fingerprinting/fingerprint-overrides/cdp-detection-bypass.js.map +1 -0
  134. package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.d.ts +6 -0
  135. package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.d.ts.map +1 -0
  136. package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.js +195 -0
  137. package/dist/fingerprinting/fingerprint-overrides/client-rect-spoofing.js.map +1 -0
  138. package/dist/fingerprinting/fingerprint-overrides/coalesced-events-spoofing.d.ts +10 -0
  139. package/dist/fingerprinting/fingerprint-overrides/coalesced-events-spoofing.d.ts.map +1 -0
  140. package/dist/fingerprinting/fingerprint-overrides/coalesced-events-spoofing.js +195 -0
  141. package/dist/fingerprinting/fingerprint-overrides/coalesced-events-spoofing.js.map +1 -0
  142. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts +28 -0
  143. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts.map +1 -0
  144. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js +1181 -0
  145. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js.map +1 -0
  146. package/dist/fingerprinting/fingerprint-overrides/font-spoofing.d.ts +7 -0
  147. package/dist/fingerprinting/fingerprint-overrides/font-spoofing.d.ts.map +1 -0
  148. package/dist/fingerprinting/fingerprint-overrides/font-spoofing.js +171 -0
  149. package/dist/fingerprinting/fingerprint-overrides/font-spoofing.js.map +1 -0
  150. package/dist/fingerprinting/fingerprint-overrides/index.d.ts +36 -0
  151. package/dist/fingerprinting/fingerprint-overrides/index.d.ts.map +1 -0
  152. package/dist/fingerprinting/fingerprint-overrides/index.js +40 -0
  153. package/dist/fingerprinting/fingerprint-overrides/index.js.map +1 -0
  154. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.d.ts +45 -0
  155. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.d.ts.map +1 -0
  156. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js +268 -0
  157. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js.map +1 -0
  158. package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.d.ts +6 -0
  159. package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.d.ts.map +1 -0
  160. package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js +301 -0
  161. package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js.map +1 -0
  162. package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.d.ts +7 -0
  163. package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.d.ts.map +1 -0
  164. package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.js +58 -0
  165. package/dist/fingerprinting/fingerprint-overrides/mouse-humanization.js.map +1 -0
  166. package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.d.ts +6 -0
  167. package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.d.ts.map +1 -0
  168. package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.js +249 -0
  169. package/dist/fingerprinting/fingerprint-overrides/performance-spoofing.js.map +1 -0
  170. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts +33 -0
  171. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts.map +1 -0
  172. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js +618 -0
  173. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js.map +1 -0
  174. package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.d.ts +13 -0
  175. package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.d.ts.map +1 -0
  176. package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.js +356 -0
  177. package/dist/fingerprinting/fingerprint-overrides/prototype-integrity.js.map +1 -0
  178. package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.d.ts +18 -0
  179. package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.d.ts.map +1 -0
  180. package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.js +171 -0
  181. package/dist/fingerprinting/fingerprint-overrides/runtime-enable-bypass.js.map +1 -0
  182. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.d.ts +55 -0
  183. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.d.ts.map +1 -0
  184. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js +244 -0
  185. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js.map +1 -0
  186. package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts +14 -0
  187. package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts.map +1 -0
  188. package/dist/fingerprinting/fingerprint-overrides/stealth-script.js +925 -0
  189. package/dist/fingerprinting/fingerprint-overrides/stealth-script.js.map +1 -0
  190. package/dist/fingerprinting/fingerprint-overrides/storage-consistency.d.ts +13 -0
  191. package/dist/fingerprinting/fingerprint-overrides/storage-consistency.d.ts.map +1 -0
  192. package/dist/fingerprinting/fingerprint-overrides/storage-consistency.js +346 -0
  193. package/dist/fingerprinting/fingerprint-overrides/storage-consistency.js.map +1 -0
  194. package/dist/fingerprinting/fingerprint-overrides/timing-consistency.d.ts +13 -0
  195. package/dist/fingerprinting/fingerprint-overrides/timing-consistency.d.ts.map +1 -0
  196. package/dist/fingerprinting/fingerprint-overrides/timing-consistency.js +264 -0
  197. package/dist/fingerprinting/fingerprint-overrides/timing-consistency.js.map +1 -0
  198. package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts +27 -0
  199. package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts.map +1 -0
  200. package/dist/fingerprinting/fingerprint-overrides/ua-ch.js +213 -0
  201. package/dist/fingerprinting/fingerprint-overrides/ua-ch.js.map +1 -0
  202. package/dist/fingerprinting/fingerprint-overrides/utils.d.ts +12 -0
  203. package/dist/fingerprinting/fingerprint-overrides/utils.d.ts.map +1 -0
  204. package/dist/fingerprinting/fingerprint-overrides/utils.js +517 -0
  205. package/dist/fingerprinting/fingerprint-overrides/utils.js.map +1 -0
  206. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.d.ts +12 -0
  207. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.d.ts.map +1 -0
  208. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js +215 -0
  209. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js.map +1 -0
  210. package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.d.ts +6 -0
  211. package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.d.ts.map +1 -0
  212. package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.js +202 -0
  213. package/dist/fingerprinting/fingerprint-overrides/webgpu-spoofing.js.map +1 -0
  214. package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.d.ts +6 -0
  215. package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.d.ts.map +1 -0
  216. package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js +188 -0
  217. package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js.map +1 -0
  218. package/dist/index.d.ts +4 -0
  219. package/dist/index.d.ts.map +1 -1
  220. package/dist/index.js +2 -0
  221. package/dist/index.js.map +1 -1
  222. package/dist/launcher-wrap.d.ts +2 -2
  223. package/dist/launcher-wrap.d.ts.map +1 -1
  224. package/dist/launcher-wrap.js.map +1 -1
  225. package/dist/page.d.ts +160 -13
  226. package/dist/page.d.ts.map +1 -1
  227. package/dist/page.js +1027 -42
  228. package/dist/page.js.map +1 -1
  229. package/dist/tsconfig.build.tsbuildinfo +1 -1
  230. package/package.json +8 -4
@@ -0,0 +1,925 @@
1
+ /**
2
+ * Base stealth script for hiding automation indicators
3
+ * Includes error stack hiding, console patching, and automation flags removal
4
+ *
5
+ * 2024-2025 Enhancements:
6
+ * - deviceMemory spoofing
7
+ * - pdfViewerEnabled consistency
8
+ * - Notification.permission handling
9
+ * - Bluetooth/USB/Serial API masking
10
+ * - Speech synthesis voice spoofing
11
+ * - Credentials API consistency
12
+ */
13
+ export const createStealthScript = () => {
14
+ return `
15
+ (() => {
16
+ 'use strict';
17
+
18
+ // Enhanced stealth script for 2025 - December
19
+
20
+ // Helper functions
21
+ const wrapNative = (fnName) => {
22
+ const nativeCode = 'function ' + fnName + '() { [native code] }';
23
+ return new Proxy(function() {}, {
24
+ get(target, prop) {
25
+ if (prop === 'toString') {
26
+ return () => nativeCode;
27
+ }
28
+ return Reflect.get(target, prop);
29
+ },
30
+ apply(target, thisArg, args) {
31
+ return undefined;
32
+ }
33
+ });
34
+ };
35
+
36
+ // Generate consistent session seed for stable values
37
+ const generateSessionSeed = () => {
38
+ const ua = navigator.userAgent || '';
39
+ const screen = window.screen;
40
+ const seed = ua.length + (screen.width || 0) + (screen.height || 0);
41
+ return seed;
42
+ };
43
+
44
+ const sessionSeed = generateSessionSeed();
45
+
46
+ // Helper to safely define property with guards
47
+ const safeDefineProperty = (obj, prop, descriptor) => {
48
+ try {
49
+ const existing = Object.getOwnPropertyDescriptor(obj, prop);
50
+ if (existing && existing.configurable === false) {
51
+ return false; // Cannot redefine
52
+ }
53
+ // Always use configurable: true to allow other scripts to modify
54
+ Object.defineProperty(obj, prop, {
55
+ ...descriptor,
56
+ configurable: true
57
+ });
58
+ return true;
59
+ } catch (e) {
60
+ return false;
61
+ }
62
+ };
63
+
64
+ // Helper to safely define getter property
65
+ const safeDefineGetter = (obj, prop, getter, enumerable = true) => {
66
+ return safeDefineProperty(obj, prop, {
67
+ get: getter,
68
+ enumerable: enumerable
69
+ });
70
+ };
71
+
72
+ // 1. Error Stack Hiding
73
+ // NOTE: Removed - this was returning a HARDCODED fake stack for ALL errors
74
+ // (chrome-extension://invalid/0.js) with configurable:false, which blocked
75
+ // runtime-enable-bypass.ts from applying proper stack sanitization.
76
+ // Stack trace protection is now handled by runtime-enable-bypass.ts.
77
+ const hideErrorStack = () => {};
78
+
79
+ // 2. Console Patching
80
+ // NOTE: Removed - wrapping ALL console methods in double-Proxy is detectable
81
+ // and conflicts with runtime-enable-bypass.ts which handles the actual
82
+ // detection vector (console.debug Error serialization) surgically.
83
+ const patchConsole = () => {};
84
+
85
+ // 3. WebDriver and Automation Flags Removal (2025)
86
+ const removeAutomationFlags = () => {
87
+ // Remove webdriver (with guard)
88
+ if (navigator.webdriver) {
89
+ safeDefineGetter(navigator, 'webdriver', () => undefined, false);
90
+ }
91
+
92
+ // Remove automation indicators
93
+ const automationProperties = [
94
+ 'webdriver', '_Selenium_IDE_Recorder', '_selenium', 'callSelenium',
95
+ '_WEBDRIVER_ELEM_CACHE', '__webdriver_script_fn', '__driver_evaluate',
96
+ '__webdriver_evaluate', '__selenium_evaluate', '__fxdriver_evaluate',
97
+ '__driver_unwrapped', '__webdriver_unwrapped', '__selenium_unwrapped',
98
+ '__fxdriver_unwrapped', '__webdriver_scripts_executed',
99
+ '__webdriver_script_func', '__webdriver_script_function',
100
+ '$cdc_asdjflasutopfhvcZLmcfl_', '$chrome_asyncScriptInfo',
101
+ '__$webdriverAsyncExecutor', '__lastWatirAlert', '__lastWatirConfirm',
102
+ '__lastWatirPrompt', '_WEBDRIVER_ELEM_CACHE', 'ChromeDriverw',
103
+ 'driver-evaluate', 'webdriver-evaluate', 'selenium-evaluate',
104
+ 'webdriverCommand', 'webdriver-evaluate-response'
105
+ ];
106
+
107
+ automationProperties.forEach(prop => {
108
+ try {
109
+ delete window[prop];
110
+ delete document[prop];
111
+ delete navigator[prop];
112
+ } catch (e) {}
113
+ });
114
+
115
+ // Ensure window.chrome exists (handled more fully by spoofChromeRuntime)
116
+ // NOTE: Removed stack-trace-based chrome getter that created new Error()
117
+ // on every access - expensive and broken since stack sanitization removes
118
+ // the markers it checked for.
119
+ };
120
+
121
+ // 4. CDP Runtime.enable Detection Prevention
122
+ // NOTE: Removed entirely. This was:
123
+ // - Blocking ALL Object.defineProperty(*, 'stack', ...) calls (broke our own code)
124
+ // - Replacing Error constructor with Proxy returning hardcoded fake stacks
125
+ // Both are handled properly by runtime-enable-bypass.ts with surgical stack sanitization.
126
+ const preventRuntimeEnableDetection = () => {};
127
+
128
+ // 5. Plugin and MimeType Spoofing (2025)
129
+ const spoofPlugins = () => {
130
+ // Chrome 120+ only reports PDF-related plugins
131
+ // Native Client was removed in Chrome 76 (2019)
132
+ const pluginData = [
133
+ {
134
+ name: 'PDF Viewer',
135
+ filename: 'internal-pdf-viewer',
136
+ description: 'Portable Document Format'
137
+ },
138
+ {
139
+ name: 'Chrome PDF Viewer',
140
+ filename: 'internal-pdf-viewer',
141
+ description: 'Portable Document Format'
142
+ },
143
+ {
144
+ name: 'Chromium PDF Viewer',
145
+ filename: 'internal-pdf-viewer',
146
+ description: 'Portable Document Format'
147
+ },
148
+ {
149
+ name: 'Microsoft Edge PDF Viewer',
150
+ filename: 'internal-pdf-viewer',
151
+ description: 'Portable Document Format'
152
+ },
153
+ {
154
+ name: 'WebKit built-in PDF',
155
+ filename: 'internal-pdf-viewer',
156
+ description: 'Portable Document Format'
157
+ }
158
+ ];
159
+
160
+ const mimeData = [
161
+ {
162
+ type: 'application/pdf',
163
+ suffixes: 'pdf',
164
+ description: 'Portable Document Format'
165
+ },
166
+ {
167
+ type: 'text/pdf',
168
+ suffixes: 'pdf',
169
+ description: 'Portable Document Format'
170
+ }
171
+ ];
172
+
173
+ // Create fake plugins using Object.defineProperty for read-only properties
174
+ const fakePlugins = pluginData.map((p, index) => {
175
+ const plugin = Object.create(Plugin.prototype);
176
+ Object.defineProperty(plugin, 'name', { value: p.name, writable: false, enumerable: true });
177
+ Object.defineProperty(plugin, 'filename', { value: p.filename, writable: false, enumerable: true });
178
+ Object.defineProperty(plugin, 'description', { value: p.description, writable: false, enumerable: true });
179
+ Object.defineProperty(plugin, 'length', { value: 1, writable: false, enumerable: true });
180
+ plugin[0] = mimeData[index] || mimeData[0];
181
+ return plugin;
182
+ });
183
+
184
+ // Create fake mimeTypes using Object.defineProperty for read-only properties
185
+ const fakeMimeTypes = mimeData.map((m, index) => {
186
+ const mimeType = Object.create(MimeType.prototype);
187
+ Object.defineProperty(mimeType, 'type', { value: m.type, writable: false, enumerable: true });
188
+ Object.defineProperty(mimeType, 'suffixes', { value: m.suffixes, writable: false, enumerable: true });
189
+ Object.defineProperty(mimeType, 'description', { value: m.description, writable: false, enumerable: true });
190
+ Object.defineProperty(mimeType, 'enabledPlugin', { value: fakePlugins[0], writable: false, enumerable: true });
191
+ return mimeType;
192
+ });
193
+
194
+ // Override navigator.plugins (with guard)
195
+ try {
196
+ const pluginsGetter = () => {
197
+ const arr = Object.create(PluginArray.prototype);
198
+ fakePlugins.forEach((p, i) => {
199
+ arr[i] = p;
200
+ arr[p.name] = p;
201
+ });
202
+ // Use Object.defineProperty for read-only properties
203
+ Object.defineProperty(arr, 'length', { value: fakePlugins.length, writable: false, enumerable: true });
204
+ Object.defineProperty(arr, 'item', { value: (index) => arr[index] || null, writable: false, enumerable: false });
205
+ Object.defineProperty(arr, 'namedItem', { value: (name) => arr[name] || null, writable: false, enumerable: false });
206
+ Object.defineProperty(arr, 'refresh', { value: () => {}, writable: false, enumerable: false });
207
+ return arr;
208
+ };
209
+ safeDefineGetter(navigator, 'plugins', pluginsGetter);
210
+
211
+ // Override navigator.mimeTypes (with guard)
212
+ const mimeTypesGetter = () => {
213
+ const arr = Object.create(MimeTypeArray.prototype);
214
+ fakeMimeTypes.forEach((m, i) => {
215
+ arr[i] = m;
216
+ arr[m.type] = m;
217
+ });
218
+ // Use Object.defineProperty for read-only properties
219
+ Object.defineProperty(arr, 'length', { value: fakeMimeTypes.length, writable: false, enumerable: true });
220
+ Object.defineProperty(arr, 'item', { value: (index) => arr[index] || null, writable: false, enumerable: false });
221
+ Object.defineProperty(arr, 'namedItem', { value: (name) => arr[name] || null, writable: false, enumerable: false });
222
+ return arr;
223
+ };
224
+ safeDefineGetter(navigator, 'mimeTypes', mimeTypesGetter);
225
+ } catch (e) {}
226
+ };
227
+
228
+ // 6. Permission API Spoofing (2025) - Fixed to return consistent Promise identity
229
+ const spoofPermissions = () => {
230
+ if (!navigator.permissions) return;
231
+
232
+ const promiseCache = new Map();
233
+ const originalQuery = navigator.permissions.query;
234
+
235
+ navigator.permissions.query = function(descriptor) {
236
+ // Common permissions that should be granted for a normal user
237
+ const allowedPermissions = ['geolocation', 'notifications', 'camera', 'microphone'];
238
+
239
+ if (descriptor && allowedPermissions.includes(descriptor.name)) {
240
+ // Return the same Promise instance for identical queries (Datadome checks this)
241
+ const key = JSON.stringify(descriptor);
242
+ if (promiseCache.has(key)) {
243
+ return promiseCache.get(key);
244
+ }
245
+
246
+ const promise = Promise.resolve({
247
+ state: 'prompt',
248
+ onchange: null,
249
+ addEventListener: () => {},
250
+ removeEventListener: () => {},
251
+ dispatchEvent: () => true
252
+ });
253
+
254
+ promiseCache.set(key, promise);
255
+ return promise;
256
+ }
257
+
258
+ return originalQuery.apply(this, arguments);
259
+ };
260
+ };
261
+
262
+ // 7. Battery API Spoofing (2025)
263
+ const spoofBatteryAPI = () => {
264
+ if ('getBattery' in navigator) {
265
+ // Use session seed for deterministic battery level
266
+ const batteryLevel = 0.92 + ((sessionSeed % 80) / 1000); // 0.92-0.999
267
+ navigator.getBattery = async () => {
268
+ return {
269
+ charging: true,
270
+ chargingTime: 0,
271
+ dischargingTime: Infinity,
272
+ level: batteryLevel,
273
+ onchargingchange: null,
274
+ onchargingtimechange: null,
275
+ ondischargingtimechange: null,
276
+ onlevelchange: null,
277
+ addEventListener: () => {},
278
+ removeEventListener: () => {},
279
+ dispatchEvent: () => true
280
+ };
281
+ };
282
+ }
283
+ };
284
+
285
+ // 8. Connection API Spoofing (2025)
286
+ const spoofConnectionAPI = () => {
287
+ if ('connection' in navigator || 'mozConnection' in navigator || 'webkitConnection' in navigator) {
288
+ const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection;
289
+ if (connection) {
290
+ try {
291
+ Object.defineProperty(connection, 'rtt', { value: 50, writable: false });
292
+ Object.defineProperty(connection, 'downlink', { value: 10.0, writable: false });
293
+ Object.defineProperty(connection, 'effectiveType', { value: '4g', writable: false });
294
+ Object.defineProperty(connection, 'saveData', { value: false, writable: false });
295
+ } catch (e) {}
296
+ }
297
+ }
298
+ };
299
+
300
+ // 9. Chrome Runtime API Spoofing (2025) - NEW
301
+ const spoofChromeRuntime = () => {
302
+ if (!window.chrome?.runtime) {
303
+ const runtime = {
304
+ PlatformOs: { MAC: 'mac', WIN: 'win', ANDROID: 'android', CROS: 'cros', LINUX: 'linux', OPENBSD: 'openbsd' },
305
+ PlatformArch: { ARM: 'arm', ARM64: 'arm64', MIPS: 'mips', MIPS64: 'mips64', X86_32: 'x86-32', X86_64: 'x86-64' },
306
+ PlatformNaclArch: { ARM: 'arm', MIPS: 'mips', MIPS64: 'mips64', X86_32: 'x86-32', X86_64: 'x86-64' },
307
+ RequestUpdateCheckStatus: { THROTTLED: 'throttled', NO_UPDATE: 'no_update', UPDATE_AVAILABLE: 'update_available' },
308
+ OnInstalledReason: { INSTALL: 'install', UPDATE: 'update', CHROME_UPDATE: 'chrome_update', SHARED_MODULE_UPDATE: 'shared_module_update' },
309
+ OnRestartRequiredReason: { APP_UPDATE: 'app_update', OS_UPDATE: 'os_update', PERIODIC: 'periodic' },
310
+ getManifest: () => ({}),
311
+ // Real Chrome extension IDs are 32 lowercase alpha chars (a-p, base16 with a-p)
312
+ id: undefined,
313
+ connect: () => ({
314
+ name: '',
315
+ disconnect: () => {},
316
+ onDisconnect: { addListener: () => {}, removeListener: () => {} },
317
+ onMessage: { addListener: () => {}, removeListener: () => {} },
318
+ postMessage: () => {}
319
+ }),
320
+ sendMessage: () => {},
321
+ getURL: (path) => '',
322
+ onConnect: { addListener: () => {}, removeListener: () => {} },
323
+ onMessage: { addListener: () => {}, removeListener: () => {} },
324
+ onStartup: { addListener: () => {}, removeListener: () => {} },
325
+ onInstalled: { addListener: () => {}, removeListener: () => {} },
326
+ onSuspend: { addListener: () => {}, removeListener: () => {} },
327
+ onSuspendCanceled: { addListener: () => {}, removeListener: () => {} },
328
+ onUpdateAvailable: { addListener: () => {}, removeListener: () => {} },
329
+ onBrowserUpdateAvailable: { addListener: () => {}, removeListener: () => {} },
330
+ onRestartRequired: { addListener: () => {}, removeListener: () => {} },
331
+ openOptionsPage: () => {},
332
+ setUninstallURL: () => {},
333
+ reload: () => {},
334
+ requestUpdateCheck: () => Promise.resolve(['no_update', {}]),
335
+ restart: () => {},
336
+ restartAfterDelay: () => {},
337
+ getPlatformInfo: () => Promise.resolve({
338
+ os: 'win',
339
+ arch: 'x86-64',
340
+ nacl_arch: 'x86-64'
341
+ }),
342
+ getPackageDirectoryEntry: () => Promise.resolve({}),
343
+ lastError: null
344
+ };
345
+
346
+ if (!window.chrome) window.chrome = {};
347
+ safeDefineProperty(window.chrome, 'runtime', {
348
+ value: runtime,
349
+ enumerable: true,
350
+ writable: false
351
+ });
352
+ }
353
+ };
354
+
355
+ // 10. Device Memory Spoofing (2024-2025)
356
+ const spoofDeviceMemory = () => {
357
+ const platform = navigator.platform || 'Win32';
358
+
359
+ // Platform-appropriate device memory values
360
+ const memoryConfig = {
361
+ 'Win32': [4, 8, 16], // Most Windows PCs have 4-16GB
362
+ 'MacIntel': [8, 16], // Macs typically have 8-16GB
363
+ 'Linux x86_64': [4, 8, 16]
364
+ };
365
+
366
+ const memories = memoryConfig[platform] || memoryConfig['Win32'];
367
+ // Use session seed for consistency
368
+ const selectedMemory = memories[sessionSeed % memories.length];
369
+
370
+ // Use guard to avoid conflicts with other scripts
371
+ if ('deviceMemory' in navigator) {
372
+ safeDefineGetter(navigator, 'deviceMemory', () => selectedMemory);
373
+ }
374
+ };
375
+
376
+ // 11. PDF Viewer Enabled Spoofing (2024-2025)
377
+ const spoofPdfViewerEnabled = () => {
378
+ // Chrome always has PDF viewer enabled (use guard)
379
+ safeDefineGetter(navigator, 'pdfViewerEnabled', () => true);
380
+ };
381
+
382
+ // 12. Notification Permission Spoofing (2024-2025)
383
+ const spoofNotificationPermission = () => {
384
+ if ('Notification' in window) {
385
+ // Override the permission property to return 'default' (user hasn't been asked) - with guard
386
+ safeDefineGetter(Notification, 'permission', () => 'default');
387
+
388
+ // Override requestPermission to behave normally
389
+ const originalRequestPermission = Notification.requestPermission;
390
+ Notification.requestPermission = function(callback) {
391
+ // Return a promise that resolves to 'default' or 'denied'
392
+ const result = Promise.resolve('default');
393
+ if (callback && typeof callback === 'function') {
394
+ result.then(callback);
395
+ }
396
+ return result;
397
+ };
398
+ }
399
+ };
400
+
401
+ // 13. Bluetooth API Spoofing (2024-2025)
402
+ const spoofBluetoothAPI = () => {
403
+ if ('bluetooth' in navigator) {
404
+ // Make bluetooth appear available but return empty results
405
+ const fakeBluetooth = {
406
+ getAvailability: () => Promise.resolve(true),
407
+ requestDevice: () => Promise.reject(new DOMException('User cancelled the requestDevice() chooser.', 'NotFoundError')),
408
+ getDevices: () => Promise.resolve([]),
409
+ addEventListener: () => {},
410
+ removeEventListener: () => {},
411
+ dispatchEvent: () => true
412
+ };
413
+
414
+ safeDefineGetter(navigator, 'bluetooth', () => fakeBluetooth);
415
+ }
416
+ };
417
+
418
+ // 14. USB API Spoofing (2024-2025)
419
+ const spoofUSBAPI = () => {
420
+ if ('usb' in navigator) {
421
+ const fakeUSB = {
422
+ getDevices: () => Promise.resolve([]),
423
+ requestDevice: () => Promise.reject(new DOMException('No device selected.', 'NotFoundError')),
424
+ addEventListener: () => {},
425
+ removeEventListener: () => {},
426
+ dispatchEvent: () => true,
427
+ onconnect: null,
428
+ ondisconnect: null
429
+ };
430
+
431
+ safeDefineGetter(navigator, 'usb', () => fakeUSB);
432
+ }
433
+ };
434
+
435
+ // 15. Serial API Spoofing (2024-2025)
436
+ const spoofSerialAPI = () => {
437
+ if ('serial' in navigator) {
438
+ const fakeSerial = {
439
+ getPorts: () => Promise.resolve([]),
440
+ requestPort: () => Promise.reject(new DOMException('No port selected.', 'NotFoundError')),
441
+ addEventListener: () => {},
442
+ removeEventListener: () => {},
443
+ dispatchEvent: () => true,
444
+ onconnect: null,
445
+ ondisconnect: null
446
+ };
447
+
448
+ safeDefineGetter(navigator, 'serial', () => fakeSerial);
449
+ }
450
+ };
451
+
452
+ // 16. Speech Synthesis Voices Spoofing (2024-2025)
453
+ const spoofSpeechSynthesis = () => {
454
+ if ('speechSynthesis' in window) {
455
+ const platform = navigator.platform || 'Win32';
456
+
457
+ // Platform-specific voices
458
+ const voiceConfigs = {
459
+ 'Win32': [
460
+ { name: 'Microsoft David - English (United States)', lang: 'en-US', localService: true, default: true },
461
+ { name: 'Microsoft Zira - English (United States)', lang: 'en-US', localService: true, default: false },
462
+ { name: 'Microsoft Mark - English (United States)', lang: 'en-US', localService: true, default: false },
463
+ { name: 'Google US English', lang: 'en-US', localService: false, default: false },
464
+ { name: 'Google UK English Female', lang: 'en-GB', localService: false, default: false },
465
+ { name: 'Google UK English Male', lang: 'en-GB', localService: false, default: false }
466
+ ],
467
+ 'MacIntel': [
468
+ { name: 'Alex', lang: 'en-US', localService: true, default: true },
469
+ { name: 'Samantha', lang: 'en-US', localService: true, default: false },
470
+ { name: 'Daniel', lang: 'en-GB', localService: true, default: false },
471
+ { name: 'Google US English', lang: 'en-US', localService: false, default: false }
472
+ ],
473
+ 'Linux x86_64': [
474
+ { name: 'Google US English', lang: 'en-US', localService: false, default: true },
475
+ { name: 'Google UK English Female', lang: 'en-GB', localService: false, default: false }
476
+ ]
477
+ };
478
+
479
+ const voices = voiceConfigs[platform] || voiceConfigs['Win32'];
480
+
481
+ // Create SpeechSynthesisVoice-like objects
482
+ const fakeVoices = voices.map(v => ({
483
+ voiceURI: v.name,
484
+ name: v.name,
485
+ lang: v.lang,
486
+ localService: v.localService,
487
+ default: v.default
488
+ }));
489
+
490
+ // Override getVoices
491
+ const originalGetVoices = speechSynthesis.getVoices;
492
+ speechSynthesis.getVoices = function() {
493
+ // Return our platform-appropriate voices
494
+ return fakeVoices;
495
+ };
496
+
497
+ // Trigger voiceschanged event after a delay to simulate loading
498
+ setTimeout(() => {
499
+ try {
500
+ const event = new Event('voiceschanged');
501
+ speechSynthesis.dispatchEvent(event);
502
+ } catch (e) {}
503
+ }, 100);
504
+ }
505
+ };
506
+
507
+ // 17. Credentials API Spoofing (2024-2025)
508
+ const spoofCredentialsAPI = () => {
509
+ if ('credentials' in navigator) {
510
+ const originalGet = navigator.credentials.get;
511
+ const originalCreate = navigator.credentials.create;
512
+ const originalStore = navigator.credentials.store;
513
+
514
+ // Make credentials API behave like a normal browser
515
+ navigator.credentials.get = function(options) {
516
+ // For publicKey (WebAuthn), reject like a normal user cancellation
517
+ if (options && options.publicKey) {
518
+ return Promise.reject(new DOMException(
519
+ 'The operation either timed out or was not allowed.',
520
+ 'NotAllowedError'
521
+ ));
522
+ }
523
+ // For password credentials, return null (no saved credentials)
524
+ return Promise.resolve(null);
525
+ };
526
+
527
+ navigator.credentials.create = function(options) {
528
+ if (options && options.publicKey) {
529
+ return Promise.reject(new DOMException(
530
+ 'The operation either timed out or was not allowed.',
531
+ 'NotAllowedError'
532
+ ));
533
+ }
534
+ return originalCreate.apply(this, arguments);
535
+ };
536
+
537
+ navigator.credentials.store = function(credential) {
538
+ // Accept but don't actually store
539
+ return Promise.resolve(credential);
540
+ };
541
+ }
542
+ };
543
+
544
+ // 18. HID API Spoofing (2024-2025)
545
+ const spoofHIDAPI = () => {
546
+ if ('hid' in navigator) {
547
+ const fakeHID = {
548
+ getDevices: () => Promise.resolve([]),
549
+ requestDevice: () => Promise.reject(new DOMException('No device selected.', 'NotFoundError')),
550
+ addEventListener: () => {},
551
+ removeEventListener: () => {},
552
+ dispatchEvent: () => true,
553
+ onconnect: null,
554
+ ondisconnect: null
555
+ };
556
+
557
+ safeDefineGetter(navigator, 'hid', () => fakeHID);
558
+ }
559
+ };
560
+
561
+ // 19. Gamepad API Spoofing (2024-2025)
562
+ const spoofGamepadAPI = () => {
563
+ // Return empty array for getGamepads
564
+ const originalGetGamepads = navigator.getGamepads;
565
+ if (originalGetGamepads) {
566
+ navigator.getGamepads = function() {
567
+ // Return empty array like no gamepads connected
568
+ return [];
569
+ };
570
+ }
571
+ };
572
+
573
+ // 20. Clipboard API Protection (2024-2025)
574
+ const spoofClipboardAPI = () => {
575
+ if (navigator.clipboard) {
576
+ const originalReadText = navigator.clipboard.readText;
577
+ const originalRead = navigator.clipboard.read;
578
+
579
+ // Make clipboard read behave like permission not granted
580
+ navigator.clipboard.readText = function() {
581
+ return Promise.reject(new DOMException(
582
+ 'Read permission denied.',
583
+ 'NotAllowedError'
584
+ ));
585
+ };
586
+
587
+ navigator.clipboard.read = function() {
588
+ return Promise.reject(new DOMException(
589
+ 'Read permission denied.',
590
+ 'NotAllowedError'
591
+ ));
592
+ };
593
+ }
594
+ };
595
+
596
+ // 21. Do Not Track Spoofing (2024-2025)
597
+ const spoofDoNotTrack = () => {
598
+ // Most real users have DNT disabled or not set
599
+ safeDefineGetter(navigator, 'doNotTrack', () => null);
600
+ };
601
+
602
+ // 22. Global Privacy Control Spoofing (2024-2025)
603
+ const spoofGlobalPrivacyControl = () => {
604
+ // Most users don't have GPC enabled
605
+ safeDefineGetter(navigator, 'globalPrivacyControl', () => false);
606
+ };
607
+
608
+ // 23. Keyboard API Spoofing (2024-2025) - DataDome checks getLayoutMap()
609
+ const spoofKeyboardAPI = () => {
610
+ // Full US QWERTY keyboard layout map
611
+ const qwertyLayoutMap = new Map([
612
+ ['Backquote', '\`'], ['Digit1', '1'], ['Digit2', '2'], ['Digit3', '3'],
613
+ ['Digit4', '4'], ['Digit5', '5'], ['Digit6', '6'], ['Digit7', '7'],
614
+ ['Digit8', '8'], ['Digit9', '9'], ['Digit0', '0'], ['Minus', '-'],
615
+ ['Equal', '='], ['Backspace', ''], ['Tab', ''], ['KeyQ', 'q'],
616
+ ['KeyW', 'w'], ['KeyE', 'e'], ['KeyR', 'r'], ['KeyT', 't'],
617
+ ['KeyY', 'y'], ['KeyU', 'u'], ['KeyI', 'i'], ['KeyO', 'o'],
618
+ ['KeyP', 'p'], ['BracketLeft', '['], ['BracketRight', ']'],
619
+ ['Backslash', '\\\\'], ['CapsLock', ''], ['KeyA', 'a'], ['KeyS', 's'],
620
+ ['KeyD', 'd'], ['KeyF', 'f'], ['KeyG', 'g'], ['KeyH', 'h'],
621
+ ['KeyJ', 'j'], ['KeyK', 'k'], ['KeyL', 'l'], ['Semicolon', ';'],
622
+ ['Quote', "'"], ['Enter', ''], ['ShiftLeft', ''], ['KeyZ', 'z'],
623
+ ['KeyX', 'x'], ['KeyC', 'c'], ['KeyV', 'v'], ['KeyB', 'b'],
624
+ ['KeyN', 'n'], ['KeyM', 'm'], ['Comma', ','], ['Period', '.'],
625
+ ['Slash', '/'], ['ShiftRight', ''], ['ControlLeft', ''],
626
+ ['AltLeft', ''], ['Space', ' '], ['AltRight', ''], ['ControlRight', ''],
627
+ ['ArrowLeft', ''], ['ArrowUp', ''], ['ArrowDown', ''], ['ArrowRight', ''],
628
+ ['NumpadDivide', '/'], ['NumpadMultiply', '*'], ['NumpadSubtract', '-'],
629
+ ['Numpad7', '7'], ['Numpad8', '8'], ['Numpad9', '9'], ['NumpadAdd', '+'],
630
+ ['Numpad4', '4'], ['Numpad5', '5'], ['Numpad6', '6'], ['Numpad1', '1'],
631
+ ['Numpad2', '2'], ['Numpad3', '3'], ['NumpadEnter', ''], ['Numpad0', '0'],
632
+ ['NumpadDecimal', '.']
633
+ ]);
634
+
635
+ // Create a KeyboardLayoutMap-like object
636
+ const createLayoutMap = () => {
637
+ const map = {
638
+ entries: function* () { yield* qwertyLayoutMap.entries(); },
639
+ keys: function* () { yield* qwertyLayoutMap.keys(); },
640
+ values: function* () { yield* qwertyLayoutMap.values(); },
641
+ forEach: (callback) => qwertyLayoutMap.forEach(callback),
642
+ get: (key) => qwertyLayoutMap.get(key),
643
+ has: (key) => qwertyLayoutMap.has(key),
644
+ size: qwertyLayoutMap.size,
645
+ [Symbol.iterator]: function* () { yield* qwertyLayoutMap.entries(); }
646
+ };
647
+
648
+ // Make it look like a KeyboardLayoutMap
649
+ Object.defineProperty(map, Symbol.toStringTag, {
650
+ value: 'KeyboardLayoutMap',
651
+ configurable: true
652
+ });
653
+
654
+ return map;
655
+ };
656
+
657
+ // Cache the layout map promise for consistency (DataDome may check promise identity)
658
+ let cachedLayoutMapPromise = null;
659
+
660
+ const fakeKeyboard = {
661
+ getLayoutMap: function() {
662
+ if (!cachedLayoutMapPromise) {
663
+ cachedLayoutMapPromise = Promise.resolve(createLayoutMap());
664
+ }
665
+ return cachedLayoutMapPromise;
666
+ },
667
+ lock: function() { return Promise.resolve(); },
668
+ unlock: function() {}
669
+ };
670
+
671
+ // Register with stealth utils for centralized toString masking
672
+ const _s = typeof __stealth !== 'undefined' ? __stealth : {};
673
+ if (_s.utils) {
674
+ _s.utils.registerNativeFunction(fakeKeyboard.getLayoutMap, 'getLayoutMap');
675
+ _s.utils.registerNativeFunction(fakeKeyboard.lock, 'lock');
676
+ _s.utils.registerNativeFunction(fakeKeyboard.unlock, 'unlock');
677
+ }
678
+
679
+ safeDefineGetter(navigator, 'keyboard', () => fakeKeyboard);
680
+ };
681
+
682
+ // 24. MediaDevices API Spoofing
683
+ // NOTE: Removed - webrtc-spoofing.ts handles enumerateDevices with
684
+ // realistic hex device IDs. Having two overrides creates detectable
685
+ // double-wrapping and inconsistent device ID formats.
686
+ const spoofMediaDevicesAPI = () => {};
687
+
688
+ // 25. ServiceWorker API Protection (2024-2025) - DataDome checks ready/register
689
+ const spoofServiceWorkerAPI = () => {
690
+ if (!navigator.serviceWorker) return;
691
+
692
+ const sw = navigator.serviceWorker;
693
+
694
+ // Wrap register to work normally but look native
695
+ const originalRegister = sw.register;
696
+ if (originalRegister) {
697
+ sw.register = function(scriptURL, options) {
698
+ return originalRegister.apply(this, arguments);
699
+ };
700
+
701
+ const _s2 = typeof __stealth !== 'undefined' ? __stealth : {};
702
+ if (_s2.utils) _s2.utils.registerNativeFunction(sw.register, 'register');
703
+ }
704
+
705
+ // Ensure ready returns a proper promise
706
+ // Note: ready is a getter, we shouldn't override it as it's already a promise
707
+ };
708
+
709
+ // 26. Undefined Navigator Properties (2024-2025) - DataDome checks these
710
+ const spoofUndefinedNavigatorProps = () => {
711
+ // navigator.brave - Only present in Brave browser, must be undefined for Chrome
712
+ safeDefineGetter(navigator, 'brave', () => undefined);
713
+
714
+ // navigator.buildID - Firefox-specific, undefined for Chrome
715
+ safeDefineGetter(navigator, 'buildID', () => undefined);
716
+
717
+ // navigator.contacts - Not widely supported, should be undefined
718
+ safeDefineGetter(navigator, 'contacts', () => undefined);
719
+
720
+ // navigator.cookieDeprecationLabel - Chrome 120+ API, undefined in most cases
721
+ safeDefineGetter(navigator, 'cookieDeprecationLabel', () => undefined);
722
+
723
+ // navigator.loadPurpose - Should be undefined
724
+ safeDefineGetter(navigator, 'loadPurpose', () => undefined);
725
+ };
726
+
727
+ // 27. Worker Constructor Protection - Prevent fingerprint leakage in worker contexts
728
+ const protectWorkerConstructor = () => {
729
+ if (typeof Worker === 'undefined') return;
730
+
731
+ // Cache fingerprint values to inject into workers
732
+ const fingerprintValues = {
733
+ userAgent: navigator.userAgent,
734
+ platform: navigator.platform,
735
+ vendor: navigator.vendor || '',
736
+ language: navigator.language,
737
+ languages: JSON.stringify(navigator.languages || ['en-US']),
738
+ hardwareConcurrency: navigator.hardwareConcurrency || 8,
739
+ deviceMemory: navigator.deviceMemory || 8,
740
+ };
741
+
742
+ // Create the worker override script
743
+ const workerOverrideScript = \`
744
+ // Worker fingerprint consistency overrides
745
+ (function() {
746
+ const fingerprintValues = \${JSON.stringify(fingerprintValues)};
747
+
748
+ // Override navigator properties in worker context
749
+ if (typeof WorkerNavigator !== 'undefined' && self.navigator) {
750
+ try {
751
+ Object.defineProperty(self.navigator, 'userAgent', { get: () => fingerprintValues.userAgent });
752
+ Object.defineProperty(self.navigator, 'platform', { get: () => fingerprintValues.platform });
753
+ Object.defineProperty(self.navigator, 'vendor', { get: () => fingerprintValues.vendor });
754
+ Object.defineProperty(self.navigator, 'language', { get: () => fingerprintValues.language });
755
+ Object.defineProperty(self.navigator, 'languages', { get: () => JSON.parse(fingerprintValues.languages) });
756
+ Object.defineProperty(self.navigator, 'hardwareConcurrency', { get: () => fingerprintValues.hardwareConcurrency });
757
+ Object.defineProperty(self.navigator, 'deviceMemory', { get: () => fingerprintValues.deviceMemory });
758
+ } catch (e) {}
759
+ }
760
+ })();
761
+ \`;
762
+
763
+ const OriginalWorker = Worker;
764
+
765
+ window.Worker = function(scriptURL, options) {
766
+ // For blob URLs, we can try to prepend our overrides
767
+ if (typeof scriptURL === 'string' && scriptURL.startsWith('blob:')) {
768
+ // Can't modify blob URLs easily, but the worker will still get our overrides
769
+ // if it was created from same-origin code
770
+ }
771
+
772
+ // Create the worker normally
773
+ const worker = new OriginalWorker(scriptURL, options);
774
+
775
+ // Intercept postMessage to detect fingerprint requests
776
+ const originalPostMessage = worker.postMessage.bind(worker);
777
+ worker.postMessage = function(message, transfer) {
778
+ return originalPostMessage(message, transfer);
779
+ };
780
+
781
+ return worker;
782
+ };
783
+
784
+ // Copy static properties
785
+ window.Worker.prototype = OriginalWorker.prototype;
786
+
787
+ Object.defineProperty(window.Worker, 'name', { value: 'Worker', configurable: true });
788
+ const _s3 = typeof __stealth !== 'undefined' ? __stealth : {};
789
+ if (_s3.utils) _s3.utils.registerNativeFunction(window.Worker, 'Worker');
790
+ };
791
+
792
+ // 28. SharedWorker Protection - Similar to Worker
793
+ const protectSharedWorkerConstructor = () => {
794
+ if (typeof SharedWorker === 'undefined') return;
795
+
796
+ const OriginalSharedWorker = SharedWorker;
797
+
798
+ window.SharedWorker = function(scriptURL, options) {
799
+ const worker = new OriginalSharedWorker(scriptURL, options);
800
+ return worker;
801
+ };
802
+
803
+ // Copy prototype
804
+ window.SharedWorker.prototype = OriginalSharedWorker.prototype;
805
+
806
+ Object.defineProperty(window.SharedWorker, 'name', { value: 'SharedWorker', configurable: true });
807
+ const _s4 = typeof __stealth !== 'undefined' ? __stealth : {};
808
+ if (_s4.utils) _s4.utils.registerNativeFunction(window.SharedWorker, 'SharedWorker');
809
+ };
810
+
811
+ // 29. PostMessage Fingerprint Protection - Prevent cross-context fingerprint detection
812
+ const protectPostMessage = () => {
813
+ // Cache consistent fingerprint values
814
+ const consistentFingerprint = {
815
+ navigator: {
816
+ userAgent: navigator.userAgent,
817
+ platform: navigator.platform,
818
+ vendor: navigator.vendor,
819
+ language: navigator.language,
820
+ languages: navigator.languages ? [...navigator.languages] : ['en-US'],
821
+ hardwareConcurrency: navigator.hardwareConcurrency,
822
+ deviceMemory: navigator.deviceMemory,
823
+ maxTouchPoints: navigator.maxTouchPoints,
824
+ webdriver: undefined,
825
+ },
826
+ screen: {
827
+ width: screen.width,
828
+ height: screen.height,
829
+ availWidth: screen.availWidth,
830
+ availHeight: screen.availHeight,
831
+ colorDepth: screen.colorDepth,
832
+ pixelDepth: screen.pixelDepth,
833
+ }
834
+ };
835
+
836
+ // Listen for fingerprint requests from iframes/workers
837
+ window.addEventListener('message', function(event) {
838
+ // Detect common fingerprint request patterns
839
+ if (event.data && typeof event.data === 'object') {
840
+ // If message looks like a fingerprint request, respond with consistent values
841
+ if (event.data.type === 'fingerprintRequest' ||
842
+ event.data.action === 'getFingerprint' ||
843
+ event.data.cmd === 'getNavigator') {
844
+
845
+ if (event.source) {
846
+ try {
847
+ event.source.postMessage({
848
+ type: 'fingerprintResponse',
849
+ data: consistentFingerprint
850
+ }, event.origin || '*');
851
+ } catch (e) {}
852
+ }
853
+ }
854
+ }
855
+ }, false);
856
+
857
+ // Wrap postMessage to ensure consistent data
858
+ const originalPostMessage = window.postMessage.bind(window);
859
+ window.postMessage = function(message, targetOrigin, transfer) {
860
+ return originalPostMessage(message, targetOrigin, transfer);
861
+ };
862
+
863
+ const _s5 = typeof __stealth !== 'undefined' ? __stealth : {};
864
+ if (_s5.utils) _s5.utils.registerNativeFunction(window.postMessage, 'postMessage');
865
+ };
866
+
867
+ // Initialize all protections
868
+ const DEBUG_PREFIX = '[CDP-FP-DEBUG]';
869
+ const ERROR_PREFIX = '[CDP-FP-ERROR]';
870
+
871
+ console.log(DEBUG_PREFIX, 'Starting stealth protection injection...');
872
+
873
+ const applyProtection = (name, fn) => {
874
+ try {
875
+ fn();
876
+ console.log(DEBUG_PREFIX, \`✓ Applied \${name}\`);
877
+ return true;
878
+ } catch (e) {
879
+ console.error(ERROR_PREFIX, \`✗ Failed to apply \${name}:\`, e);
880
+ throw e; // Rethrow to make errors visible
881
+ }
882
+ };
883
+
884
+ try {
885
+ applyProtection('Error Stack Hiding', hideErrorStack);
886
+ applyProtection('Console Patching', patchConsole);
887
+ applyProtection('Automation Flags Removal', removeAutomationFlags);
888
+ applyProtection('Runtime.enable Detection Prevention', preventRuntimeEnableDetection);
889
+ applyProtection('Plugin Spoofing', spoofPlugins);
890
+ applyProtection('Permissions API Spoofing', spoofPermissions);
891
+ applyProtection('Battery API Spoofing', spoofBatteryAPI);
892
+ applyProtection('Connection API Spoofing', spoofConnectionAPI);
893
+ applyProtection('Chrome Runtime API Spoofing', spoofChromeRuntime);
894
+ // New 2024-2025 protections
895
+ applyProtection('Device Memory Spoofing', spoofDeviceMemory);
896
+ applyProtection('PDF Viewer Enabled Spoofing', spoofPdfViewerEnabled);
897
+ applyProtection('Notification Permission Spoofing', spoofNotificationPermission);
898
+ applyProtection('Bluetooth API Spoofing', spoofBluetoothAPI);
899
+ applyProtection('USB API Spoofing', spoofUSBAPI);
900
+ applyProtection('Serial API Spoofing', spoofSerialAPI);
901
+ applyProtection('Speech Synthesis Spoofing', spoofSpeechSynthesis);
902
+ applyProtection('Credentials API Spoofing', spoofCredentialsAPI);
903
+ applyProtection('HID API Spoofing', spoofHIDAPI);
904
+ applyProtection('Gamepad API Spoofing', spoofGamepadAPI);
905
+ applyProtection('Clipboard API Protection', spoofClipboardAPI);
906
+ applyProtection('Do Not Track Spoofing', spoofDoNotTrack);
907
+ applyProtection('Global Privacy Control Spoofing', spoofGlobalPrivacyControl);
908
+ // DataDome-specific protections
909
+ applyProtection('Keyboard API Spoofing', spoofKeyboardAPI);
910
+ applyProtection('MediaDevices API Spoofing', spoofMediaDevicesAPI);
911
+ applyProtection('ServiceWorker API Protection', spoofServiceWorkerAPI);
912
+ applyProtection('Undefined Navigator Props', spoofUndefinedNavigatorProps);
913
+ // Cross-context consistency protections
914
+ applyProtection('Worker Constructor Protection', protectWorkerConstructor);
915
+ applyProtection('SharedWorker Protection', protectSharedWorkerConstructor);
916
+ applyProtection('PostMessage Protection', protectPostMessage);
917
+
918
+ console.log(DEBUG_PREFIX, '✓ All stealth protections applied successfully');
919
+ } catch (e) {
920
+ console.error(ERROR_PREFIX, '✗ Failed to apply stealth protections:', e);
921
+ throw e; // Rethrow to make errors visible
922
+ }
923
+ })();`;
924
+ };
925
+ //# sourceMappingURL=stealth-script.js.map