jumpy-lion 0.1.6-beta.7 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (232) hide show
  1. package/README.md +1 -607
  2. package/browser/fonts/macos-bundle/40-macos-aliases.conf +515 -0
  3. package/browser/fonts/macos-bundle/README.md +24 -0
  4. package/browser/fonts/macos-bundle/install.sh +83 -0
  5. package/dist/browser-controller.d.ts +47 -4
  6. package/dist/browser-controller.d.ts.map +1 -1
  7. package/dist/browser-controller.js +219 -278
  8. package/dist/browser-controller.js.map +1 -1
  9. package/dist/browser-plugin.d.ts +82 -110
  10. package/dist/browser-plugin.d.ts.map +1 -1
  11. package/dist/browser-plugin.js +376 -379
  12. package/dist/browser-plugin.js.map +1 -1
  13. package/dist/browser-process/align-fingerprint-config.d.ts +36 -0
  14. package/dist/browser-process/align-fingerprint-config.d.ts.map +1 -0
  15. package/dist/browser-process/align-fingerprint-config.js +74 -0
  16. package/dist/browser-process/align-fingerprint-config.js.map +1 -0
  17. package/dist/browser-process/anti-detect-browser.d.ts +2 -2
  18. package/dist/browser-process/anti-detect-browser.js +7 -7
  19. package/dist/browser-process/anti-detect-config.d.ts +131 -2
  20. package/dist/browser-process/anti-detect-config.d.ts.map +1 -1
  21. package/dist/browser-process/anti-detect-config.js +337 -127
  22. package/dist/browser-process/anti-detect-config.js.map +1 -1
  23. package/dist/browser-process/browser.d.ts +25 -92
  24. package/dist/browser-process/browser.d.ts.map +1 -1
  25. package/dist/browser-process/browser.js +429 -73
  26. package/dist/browser-process/browser.js.map +1 -1
  27. package/dist/browser-process/fingerprint-config.d.ts +146 -0
  28. package/dist/browser-process/fingerprint-config.d.ts.map +1 -0
  29. package/dist/browser-process/fingerprint-config.js +308 -0
  30. package/dist/browser-process/fingerprint-config.js.map +1 -0
  31. package/dist/browser-process/get-chrome-executable.d.ts +6 -0
  32. package/dist/browser-process/get-chrome-executable.d.ts.map +1 -1
  33. package/dist/browser-process/get-chrome-executable.js +79 -4
  34. package/dist/browser-process/get-chrome-executable.js.map +1 -1
  35. package/dist/browser-process/gpu-family-profiles.d.ts +58 -0
  36. package/dist/browser-process/gpu-family-profiles.d.ts.map +1 -0
  37. package/dist/browser-process/gpu-family-profiles.js +480 -0
  38. package/dist/browser-process/gpu-family-profiles.js.map +1 -0
  39. package/dist/browser-process/launch-options.d.ts +301 -0
  40. package/dist/browser-process/launch-options.d.ts.map +1 -0
  41. package/dist/browser-process/launch-options.js +2 -0
  42. package/dist/browser-process/launch-options.js.map +1 -0
  43. package/dist/browser-process/port-allocator.d.ts +64 -0
  44. package/dist/browser-process/port-allocator.d.ts.map +1 -0
  45. package/dist/browser-process/port-allocator.js +198 -0
  46. package/dist/browser-process/port-allocator.js.map +1 -0
  47. package/dist/browser-process/process.d.ts +85 -0
  48. package/dist/browser-process/process.d.ts.map +1 -1
  49. package/dist/browser-process/process.js +235 -19
  50. package/dist/browser-process/process.js.map +1 -1
  51. package/dist/browser-process/signal-cleanup.d.ts +40 -0
  52. package/dist/browser-process/signal-cleanup.d.ts.map +1 -0
  53. package/dist/browser-process/signal-cleanup.js +105 -0
  54. package/dist/browser-process/signal-cleanup.js.map +1 -0
  55. package/dist/browser-process/widevine-cdm.d.ts +144 -0
  56. package/dist/browser-process/widevine-cdm.d.ts.map +1 -0
  57. package/dist/browser-process/widevine-cdm.js +298 -0
  58. package/dist/browser-process/widevine-cdm.js.map +1 -0
  59. package/dist/browser-profiles/chrome/populate-profile.d.ts.map +1 -1
  60. package/dist/browser-profiles/chrome/populate-profile.js +21 -22
  61. package/dist/browser-profiles/chrome/populate-profile.js.map +1 -1
  62. package/dist/connection/cdp-reconnection.d.ts +50 -0
  63. package/dist/connection/cdp-reconnection.d.ts.map +1 -0
  64. package/dist/connection/cdp-reconnection.js +75 -0
  65. package/dist/connection/cdp-reconnection.js.map +1 -0
  66. package/dist/connection/page-session.d.ts +114 -0
  67. package/dist/connection/page-session.d.ts.map +1 -0
  68. package/dist/connection/page-session.js +237 -0
  69. package/dist/connection/page-session.js.map +1 -0
  70. package/dist/connection/session-client.d.ts +34 -0
  71. package/dist/connection/session-client.d.ts.map +1 -0
  72. package/dist/connection/session-client.js +129 -0
  73. package/dist/connection/session-client.js.map +1 -0
  74. package/dist/crawler.d.ts +9 -88
  75. package/dist/crawler.d.ts.map +1 -1
  76. package/dist/crawler.js +157 -8
  77. package/dist/crawler.js.map +1 -1
  78. package/dist/fingerprinting/fingerprint-injector.d.ts +24 -114
  79. package/dist/fingerprinting/fingerprint-injector.d.ts.map +1 -1
  80. package/dist/fingerprinting/fingerprint-injector.js +305 -611
  81. package/dist/fingerprinting/fingerprint-injector.js.map +1 -1
  82. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts +1 -1
  83. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts.map +1 -1
  84. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js +16 -14
  85. package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js.map +1 -1
  86. package/dist/fingerprinting/fingerprint-overrides/index.d.ts +6 -2
  87. package/dist/fingerprinting/fingerprint-overrides/index.d.ts.map +1 -1
  88. package/dist/fingerprinting/fingerprint-overrides/index.js +6 -2
  89. package/dist/fingerprinting/fingerprint-overrides/index.js.map +1 -1
  90. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.d.ts +1 -1
  91. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js +4 -4
  92. package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js.map +1 -1
  93. package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js +4 -4
  94. package/dist/fingerprinting/fingerprint-overrides/navigator-override.d.ts +18 -0
  95. package/dist/fingerprinting/fingerprint-overrides/navigator-override.d.ts.map +1 -0
  96. package/dist/fingerprinting/fingerprint-overrides/navigator-override.js +136 -0
  97. package/dist/fingerprinting/fingerprint-overrides/navigator-override.js.map +1 -0
  98. package/dist/fingerprinting/fingerprint-overrides/override.d.ts +151 -0
  99. package/dist/fingerprinting/fingerprint-overrides/override.d.ts.map +1 -0
  100. package/dist/fingerprinting/fingerprint-overrides/override.js +14 -0
  101. package/dist/fingerprinting/fingerprint-overrides/override.js.map +1 -0
  102. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts.map +1 -1
  103. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js +46 -15
  104. package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js.map +1 -1
  105. package/dist/fingerprinting/fingerprint-overrides/registry.d.ts +43 -0
  106. package/dist/fingerprinting/fingerprint-overrides/registry.d.ts.map +1 -0
  107. package/dist/fingerprinting/fingerprint-overrides/registry.js +342 -0
  108. package/dist/fingerprinting/fingerprint-overrides/registry.js.map +1 -0
  109. package/dist/fingerprinting/fingerprint-overrides/screen-override.d.ts +16 -0
  110. package/dist/fingerprinting/fingerprint-overrides/screen-override.d.ts.map +1 -0
  111. package/dist/fingerprinting/fingerprint-overrides/screen-override.js +175 -0
  112. package/dist/fingerprinting/fingerprint-overrides/screen-override.js.map +1 -0
  113. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.d.ts +1 -1
  114. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js +4 -4
  115. package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js.map +1 -1
  116. package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts.map +1 -1
  117. package/dist/fingerprinting/fingerprint-overrides/stealth-script.js +75 -9
  118. package/dist/fingerprinting/fingerprint-overrides/stealth-script.js.map +1 -1
  119. package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts +1 -1
  120. package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts.map +1 -1
  121. package/dist/fingerprinting/fingerprint-overrides/ua-ch.js +34 -20
  122. package/dist/fingerprinting/fingerprint-overrides/ua-ch.js.map +1 -1
  123. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.d.ts.map +1 -1
  124. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js +25 -6
  125. package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js.map +1 -1
  126. package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js +1 -1
  127. package/dist/fingerprinting/hardware-realism.d.ts +83 -0
  128. package/dist/fingerprinting/hardware-realism.d.ts.map +1 -0
  129. package/dist/fingerprinting/hardware-realism.js +156 -0
  130. package/dist/fingerprinting/hardware-realism.js.map +1 -0
  131. package/dist/fingerprinting/injection-planner.d.ts +133 -0
  132. package/dist/fingerprinting/injection-planner.d.ts.map +1 -0
  133. package/dist/fingerprinting/injection-planner.js +497 -0
  134. package/dist/fingerprinting/injection-planner.js.map +1 -0
  135. package/dist/fingerprinting/locale-resolver.d.ts +8 -1
  136. package/dist/fingerprinting/locale-resolver.d.ts.map +1 -1
  137. package/dist/fingerprinting/locale-resolver.js +26 -3
  138. package/dist/fingerprinting/locale-resolver.js.map +1 -1
  139. package/dist/fingerprinting/non-apify-fingerprint-generator.d.ts +4 -4
  140. package/dist/fingerprinting/non-apify-fingerprint-generator.d.ts.map +1 -1
  141. package/dist/fingerprinting/non-apify-fingerprint-generator.js +24 -58
  142. package/dist/fingerprinting/non-apify-fingerprint-generator.js.map +1 -1
  143. package/dist/fingerprinting/non-apify-profiles.json +10515 -8494
  144. package/dist/fingerprinting/os-consistency.d.ts +28 -0
  145. package/dist/fingerprinting/os-consistency.d.ts.map +1 -0
  146. package/dist/fingerprinting/os-consistency.js +45 -0
  147. package/dist/fingerprinting/os-consistency.js.map +1 -0
  148. package/dist/fingerprinting/profile-quality.d.ts +25 -0
  149. package/dist/fingerprinting/profile-quality.d.ts.map +1 -0
  150. package/dist/fingerprinting/profile-quality.js +310 -0
  151. package/dist/fingerprinting/profile-quality.js.map +1 -0
  152. package/dist/fingerprinting/profile-selector.d.ts +102 -0
  153. package/dist/fingerprinting/profile-selector.d.ts.map +1 -0
  154. package/dist/fingerprinting/profile-selector.js +168 -0
  155. package/dist/fingerprinting/profile-selector.js.map +1 -0
  156. package/dist/fingerprinting/ua-alignment.d.ts +83 -0
  157. package/dist/fingerprinting/ua-alignment.d.ts.map +1 -0
  158. package/dist/fingerprinting/ua-alignment.js +197 -0
  159. package/dist/fingerprinting/ua-alignment.js.map +1 -0
  160. package/dist/fingerprinting/ua-ch-brands.d.ts +88 -0
  161. package/dist/fingerprinting/ua-ch-brands.d.ts.map +1 -0
  162. package/dist/fingerprinting/ua-ch-brands.js +174 -0
  163. package/dist/fingerprinting/ua-ch-brands.js.map +1 -0
  164. package/dist/index.d.ts +5 -0
  165. package/dist/index.d.ts.map +1 -1
  166. package/dist/index.js +6 -0
  167. package/dist/index.js.map +1 -1
  168. package/dist/input/dropdown-selector.d.ts +90 -0
  169. package/dist/input/dropdown-selector.d.ts.map +1 -0
  170. package/dist/input/dropdown-selector.js +394 -0
  171. package/dist/input/dropdown-selector.js.map +1 -0
  172. package/dist/input/element-target.d.ts +152 -0
  173. package/dist/input/element-target.d.ts.map +1 -0
  174. package/dist/input/element-target.js +461 -0
  175. package/dist/input/element-target.js.map +1 -0
  176. package/dist/input/input-emulator.d.ts +85 -0
  177. package/dist/input/input-emulator.d.ts.map +1 -0
  178. package/dist/input/input-emulator.js +325 -0
  179. package/dist/input/input-emulator.js.map +1 -0
  180. package/dist/input/input-transport.d.ts +60 -0
  181. package/dist/input/input-transport.d.ts.map +1 -0
  182. package/dist/input/input-transport.js +28 -0
  183. package/dist/input/input-transport.js.map +1 -0
  184. package/dist/input/recording-transport.d.ts +32 -0
  185. package/dist/input/recording-transport.d.ts.map +1 -0
  186. package/dist/input/recording-transport.js +43 -0
  187. package/dist/input/recording-transport.js.map +1 -0
  188. package/dist/keyboard-layout.d.ts +2 -2
  189. package/dist/keyboard-layout.js +2 -2
  190. package/dist/navigation/page-navigation.d.ts +67 -0
  191. package/dist/navigation/page-navigation.d.ts.map +1 -0
  192. package/dist/navigation/page-navigation.js +122 -0
  193. package/dist/navigation/page-navigation.js.map +1 -0
  194. package/dist/network/network-watch.d.ts +110 -0
  195. package/dist/network/network-watch.d.ts.map +1 -0
  196. package/dist/network/network-watch.js +223 -0
  197. package/dist/network/network-watch.js.map +1 -0
  198. package/dist/page.d.ts +118 -104
  199. package/dist/page.d.ts.map +1 -1
  200. package/dist/page.js +311 -1130
  201. package/dist/page.js.map +1 -1
  202. package/dist/session/inject-hook.d.ts +24 -0
  203. package/dist/session/inject-hook.d.ts.map +1 -0
  204. package/dist/session/inject-hook.js +80 -0
  205. package/dist/session/inject-hook.js.map +1 -0
  206. package/dist/session/save.d.ts +21 -0
  207. package/dist/session/save.d.ts.map +1 -0
  208. package/dist/session/save.js +163 -0
  209. package/dist/session/save.js.map +1 -0
  210. package/dist/session/tar-data-dir.d.ts +18 -0
  211. package/dist/session/tar-data-dir.d.ts.map +1 -0
  212. package/dist/session/tar-data-dir.js +105 -0
  213. package/dist/session/tar-data-dir.js.map +1 -0
  214. package/dist/session/types.d.ts +80 -0
  215. package/dist/session/types.d.ts.map +1 -0
  216. package/dist/session/types.js +29 -0
  217. package/dist/session/types.js.map +1 -0
  218. package/dist/session-profile.d.ts +102 -0
  219. package/dist/session-profile.d.ts.map +1 -0
  220. package/dist/session-profile.js +163 -0
  221. package/dist/session-profile.js.map +1 -0
  222. package/dist/tsconfig.build.tsbuildinfo +1 -1
  223. package/package.json +17 -6
  224. package/scripts/postinstall.cjs +58 -0
  225. package/dist/fingerprinting/custom-fingerprint-injector.d.ts +0 -87
  226. package/dist/fingerprinting/custom-fingerprint-injector.d.ts.map +0 -1
  227. package/dist/fingerprinting/custom-fingerprint-injector.js +0 -342
  228. package/dist/fingerprinting/custom-fingerprint-injector.js.map +0 -1
  229. package/dist/launcher-wrap.d.ts +0 -10
  230. package/dist/launcher-wrap.d.ts.map +0 -1
  231. package/dist/launcher-wrap.js +0 -11
  232. package/dist/launcher-wrap.js.map +0 -1
@@ -214,7 +214,7 @@ export const createStealthScript = () => {
214
214
  Object.defineProperty(arr, 'item', { value: (index) => arr[index] || null, writable: false, enumerable: false });
215
215
  Object.defineProperty(arr, 'namedItem', { value: (name) => arr[name] || null, writable: false, enumerable: false });
216
216
  Object.defineProperty(arr, 'refresh', { value: () => {}, writable: false, enumerable: false });
217
- // Allow for...of iteration — checked by DataDome and FingerprintJS Pro
217
+ // Allow for...of iteration - checked by DataDome and FingerprintJS Pro
218
218
  arr[Symbol.iterator] = function* () { for (let i = 0; i < fakePlugins.length; i++) yield arr[i]; };
219
219
  return arr;
220
220
  };
@@ -648,7 +648,7 @@ export const createStealthScript = () => {
648
648
  if (originalGetGamepads) {
649
649
  navigator.getGamepads = function() {
650
650
  // Real Chrome returns GamepadList with 4 null slots when no gamepads
651
- // connected — NOT an empty array. [] vs [null,null,null,null] is a
651
+ // connected - NOT an empty array. [] vs [null,null,null,null] is a
652
652
  // checked difference between headed Chrome and headless/Chromium.
653
653
  return [null, null, null, null];
654
654
  };
@@ -954,11 +954,50 @@ export const createStealthScript = () => {
954
954
  // meaning Cloudflare / Akamai / PerimeterX saw raw headless values. Move them
955
955
  // here so all crawls benefit.
956
956
  const spoofDocumentVisibility = () => {
957
+ // Capture the real (browser-native) accessors before any instance-level
958
+ // override, so we can (1) detect spurious visibilitychange events that
959
+ // fire without an underlying state transition (typical of CDP-driven
960
+ // lifecycle commands - these would expose automation if they reached
961
+ // the page), and (2) during real OS-driven transitions, briefly yield
962
+ // to the real accessors so a page's visibilitychange listener sees a
963
+ // visibilityState consistent with the event it just received (which
964
+ // is what happens on real Chrome).
965
+ let _origVisibilityGet = null;
966
+ let _origHiddenGet = null;
957
967
  try {
958
- Object.defineProperty(document, 'hidden', { get: () => false, configurable: true });
959
- Object.defineProperty(document, 'visibilityState', { get: () => 'visible', configurable: true });
968
+ const _vDesc = Object.getOwnPropertyDescriptor(Document.prototype, 'visibilityState');
969
+ const _hDesc = Object.getOwnPropertyDescriptor(Document.prototype, 'hidden');
970
+ if (_vDesc && _vDesc.get) _origVisibilityGet = _vDesc.get;
971
+ if (_hDesc && _hDesc.get) _origHiddenGet = _hDesc.get;
960
972
  } catch (e) {}
961
973
 
974
+ const installSpoof = () => {
975
+ try {
976
+ Object.defineProperty(document, 'hidden',
977
+ { get: () => false, configurable: true });
978
+ Object.defineProperty(document, 'visibilityState',
979
+ { get: () => 'visible', configurable: true });
980
+ } catch (e) {}
981
+ };
982
+ const restoreReal = () => {
983
+ try {
984
+ Object.defineProperty(document, 'hidden', {
985
+ get: function() {
986
+ return _origHiddenGet ? _origHiddenGet.call(this) : false;
987
+ },
988
+ configurable: true
989
+ });
990
+ Object.defineProperty(document, 'visibilityState', {
991
+ get: function() {
992
+ return _origVisibilityGet ? _origVisibilityGet.call(this) : 'visible';
993
+ },
994
+ configurable: true
995
+ });
996
+ } catch (e) {}
997
+ };
998
+
999
+ installSpoof();
1000
+
962
1001
  document.hasFocus = function() { return true; };
963
1002
  try {
964
1003
  Object.defineProperty(document.hasFocus, 'toString', {
@@ -967,12 +1006,39 @@ export const createStealthScript = () => {
967
1006
  });
968
1007
  } catch (e) {}
969
1008
 
970
- // Suppress CDP-lifecycle-driven visibilitychange events that expose headless state
1009
+ let _lastReal = _origVisibilityGet ? _origVisibilityGet.call(document) : 'visible';
1010
+ let _restoring = false;
1011
+
971
1012
  const origAEL = document.addEventListener.bind(document);
972
- const _hiddenEvtHandler = (e) => {
973
- if (e.type === 'visibilitychange') { e.stopImmediatePropagation(); }
1013
+ const _visibilityHandler = (e) => {
1014
+ if (e.type !== 'visibilitychange') return;
1015
+ if (!_origVisibilityGet) return;
1016
+ const real = _origVisibilityGet.call(document);
1017
+ if (real === _lastReal) {
1018
+ // Spurious dispatch (e.g. CDP-driven). Suppress so it cannot
1019
+ // betray automation through an event-without-state-change.
1020
+ e.stopImmediatePropagation();
1021
+ return;
1022
+ }
1023
+ _lastReal = real;
1024
+
1025
+ // Genuine OS-driven transition (macOS Space switch, minimize,
1026
+ // fullscreen toggle, etc.). Let the event propagate so the page's
1027
+ // render loop / animation timers can resume, but yield to the
1028
+ // real accessors for the duration of the synchronous dispatch so
1029
+ // listeners read a state consistent with the event. The spoof is
1030
+ // re-installed in the next microtask, after sync listeners have
1031
+ // finished running.
1032
+ if (!_restoring) {
1033
+ _restoring = true;
1034
+ restoreReal();
1035
+ Promise.resolve().then(() => {
1036
+ installSpoof();
1037
+ _restoring = false;
1038
+ });
1039
+ }
974
1040
  };
975
- origAEL('visibilitychange', _hiddenEvtHandler, true);
1041
+ origAEL('visibilitychange', _visibilityHandler, true);
976
1042
  };
977
1043
 
978
1044
  // 31. Encrypted Media Extensions (Widevine) Spoofing
@@ -1101,7 +1167,7 @@ export const createStealthScript = () => {
1101
1167
  applyProtection('Worker Constructor Protection', protectWorkerConstructor);
1102
1168
  applyProtection('SharedWorker Protection', protectSharedWorkerConstructor);
1103
1169
  applyProtection('PostMessage Protection', protectPostMessage);
1104
- // Chrome authenticity patches — make Chromium look like real Chrome
1170
+ // Chrome authenticity patches - make Chromium look like real Chrome
1105
1171
  applyProtection('Document Visibility Spoofing', spoofDocumentVisibility);
1106
1172
  applyProtection('EME/Widevine Spoofing', spoofEME);
1107
1173
 
@@ -1 +1 @@
1
- {"version":3,"file":"stealth-script.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/stealth-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAW,EAAE;IAC5C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA2kCL,CAAC;AACP,CAAC,CAAC"}
1
+ {"version":3,"file":"stealth-script.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/stealth-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAW,EAAE;IAC5C,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA6oCL,CAAC;AACP,CAAC,CAAC"}
@@ -23,5 +23,5 @@ export interface UAClientHintsData {
23
23
  uaFullVersion?: string;
24
24
  wow64?: boolean;
25
25
  }
26
- export declare const createUAClientHintsSpoofingScript: (platform?: string, generatedUAData?: UAClientHintsData) => string;
26
+ export declare const createUAClientHintsSpoofingScript: (platform?: string, generatedUAData?: UAClientHintsData, binaryFullVersion?: string) => string;
27
27
  //# sourceMappingURL=ua-ch.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ua-ch.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/ua-ch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,iBAAiB;IAC9B,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,eAAe,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,iCAAiC,wCAExB,iBAAiB,KACpC,MAuNF,CAAC"}
1
+ {"version":3,"file":"ua-ch.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/ua-ch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,MAAM,WAAW,iBAAiB;IAC9B,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC9C,eAAe,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,iCAAiC,wCAExB,iBAAiB,sBACf,MAAM,KAC3B,MAmOF,CAAC"}
@@ -5,7 +5,9 @@
5
5
  * to ensure UA-CH brands/versions match the generated userAgent string.
6
6
  * When not provided, falls back to hardcoded defaults.
7
7
  */
8
- export const createUAClientHintsSpoofingScript = (platform = 'Win32', generatedUAData) => {
8
+ import { resolvePlatformVersion } from '../hardware-realism.js';
9
+ import { brandListScriptExpression } from '../ua-ch-brands.js';
10
+ export const createUAClientHintsSpoofingScript = (platform = 'Win32', generatedUAData, binaryFullVersion) => {
9
11
  // When generated data is available, use it directly for consistency
10
12
  // with the generated userAgent string. Otherwise use defaults.
11
13
  let platformData;
@@ -13,30 +15,34 @@ export const createUAClientHintsSpoofingScript = (platform = 'Win32', generatedU
13
15
  let architecture;
14
16
  let bitness;
15
17
  let wow64;
18
+ // platformVersion comes from hardware-realism.ts rather than a literal, so the
19
+ // no-profile path cannot advertise a stale macOS release or a kernel version
20
+ // on Linux (real Chrome sends an empty string there) - see issue #137. Index 0
21
+ // is the most common value for the platform.
16
22
  if (generatedUAData) {
17
23
  platformData = generatedUAData.platform || 'Windows';
18
- platformVersion = generatedUAData.platformVersion || '15.0.0';
24
+ platformVersion = generatedUAData.platformVersion ?? resolvePlatformVersion(platform, 0);
19
25
  architecture = generatedUAData.architecture || 'x86';
20
26
  bitness = generatedUAData.bitness || '64';
21
27
  wow64 = generatedUAData.wow64 ?? false;
22
28
  }
23
29
  else if (platform.startsWith('Win') || platform === 'Win32') {
24
30
  platformData = 'Windows';
25
- platformVersion = '15.0.0';
31
+ platformVersion = resolvePlatformVersion('Win32', 0);
26
32
  architecture = 'x86';
27
33
  bitness = '64';
28
34
  wow64 = false;
29
35
  }
30
36
  else if (platform.startsWith('Mac')) {
31
37
  platformData = 'macOS';
32
- platformVersion = '15.3.0';
38
+ platformVersion = resolvePlatformVersion('MacIntel', 0);
33
39
  architecture = 'arm';
34
40
  bitness = '64';
35
41
  wow64 = false;
36
42
  }
37
43
  else {
38
44
  platformData = 'Linux';
39
- platformVersion = '6.8.0';
45
+ platformVersion = resolvePlatformVersion('Linux x86_64', 0);
40
46
  architecture = 'x86';
41
47
  bitness = '64';
42
48
  wow64 = false;
@@ -45,8 +51,15 @@ export const createUAClientHintsSpoofingScript = (platform = 'Win32', generatedU
45
51
  // When no generated data, we parse the version from navigator.userAgent at runtime
46
52
  // to ensure JS-side brands match the HTTP-level Sec-CH-UA headers set by
47
53
  // Network.setUserAgentOverride (which also parses from the UA string).
48
- const hasGeneratedVersion = !!generatedUAData?.uaFullVersion;
49
- const fullVersion = generatedUAData?.uaFullVersion || '';
54
+ // UA-CH keeps the REAL build version even though UA Reduction froze the UA
55
+ // string to MAJOR.0.0.0 - real Chrome 147 reports 147.0.7727.56 in
56
+ // uaFullVersion / fullVersionList. Parsing the version out of
57
+ // navigator.userAgent (the old fallback) therefore reported 147.0.0.0, a
58
+ // shape no Chrome emits and one that gets every high-entropy request
59
+ // refused (issue #131). Prefer the profile's build, then the binary's own.
60
+ const resolvedFullVersion = generatedUAData?.uaFullVersion || binaryFullVersion || '';
61
+ const hasGeneratedVersion = !!resolvedFullVersion;
62
+ const fullVersion = resolvedFullVersion;
50
63
  // Brands - use generated data if available
51
64
  const brandsJson = generatedUAData?.brands
52
65
  ? JSON.stringify(generatedUAData.brands)
@@ -66,24 +79,25 @@ export const createUAClientHintsSpoofingScript = (platform = 'Win32', generatedU
66
79
  // Parse Chrome version from UA at runtime to stay in sync with
67
80
  // HTTP-level Sec-CH-UA set by Network.setUserAgentOverride.
68
81
  const _parsedMatch = navigator.userAgent.match(/Chrome\\/([\\d.]+)/);
69
- const _rtFullVersion = _parsedMatch ? _parsedMatch[1] : '134.0.6998.88';
70
- const _rtMajorVersion = _rtFullVersion.split('.')[0];
82
+ const _rtUaVersion = _parsedMatch ? _parsedMatch[1] : '134.0.6998.88';
83
+ const _rtMajorVersion = _rtUaVersion.split('.')[0];
84
+ // UA Reduction zeroes minor/build/patch in the UA string only; UA-CH keeps
85
+ // the real build. Never derive the full version from the UA - a
86
+ // "147.0.0.0" full-version list is refused by origins that request
87
+ // high-entropy hints (issue #131).
88
+ const _rtFullVersion = ${hasGeneratedVersion ? `"${resolvedFullVersion}"` : '_rtUaVersion'};
71
89
 
72
- // Brand list - from generated fingerprint or derived from UA at runtime
90
+ // Brand list - from generated fingerprint or derived from UA at runtime.
91
+ // The runtime path derives the GREASE token and the list order from the
92
+ // major the way Chromium does (see ua-ch-brands.ts): a hardcoded
93
+ // "Not_A Brand";v="24" would contradict any major but 131 - the exact
94
+ // mismatch Naver answers with a challenge-free 418 (issue #131).
73
95
  const brands = Object.freeze(
74
- ${brandsJson || `[
75
- { brand: "Google Chrome", version: _rtMajorVersion },
76
- { brand: "Chromium", version: _rtMajorVersion },
77
- { brand: "Not_A Brand", version: "24" },
78
- ]`}.map(b => Object.freeze(b))
96
+ ${brandsJson || brandListScriptExpression('_rtMajorVersion', '_rtMajorVersion', 'major')}.map(b => Object.freeze(b))
79
97
  );
80
98
 
81
99
  const fullVersionList = Object.freeze(
82
- ${fullVersionListJson || `[
83
- { brand: "Google Chrome", version: _rtFullVersion },
84
- { brand: "Chromium", version: _rtFullVersion },
85
- { brand: "Not_A Brand", version: "24.0.0.0" },
86
- ]`}.map(b => Object.freeze(b))
100
+ ${fullVersionListJson || brandListScriptExpression('_rtMajorVersion', '_rtFullVersion', 'full')}.map(b => Object.freeze(b))
87
101
  );
88
102
 
89
103
  const mobile = false;
@@ -1 +1 @@
1
- {"version":3,"file":"ua-ch.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/ua-ch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH,MAAM,CAAC,MAAM,iCAAiC,GAAG,CAC7C,QAAQ,GAAG,OAAO,EAClB,eAAmC,EAC7B,EAAE;IACR,oEAAoE;IACpE,+DAA+D;IAC/D,IAAI,YAAoB,CAAC;IACzB,IAAI,eAAuB,CAAC;IAC5B,IAAI,YAAoB,CAAC;IACzB,IAAI,OAAe,CAAC;IACpB,IAAI,KAAc,CAAC;IAEnB,IAAI,eAAe,EAAE,CAAC;QAClB,YAAY,GAAG,eAAe,CAAC,QAAQ,IAAI,SAAS,CAAC;QACrD,eAAe,GAAG,eAAe,CAAC,eAAe,IAAI,QAAQ,CAAC;QAC9D,YAAY,GAAG,eAAe,CAAC,YAAY,IAAI,KAAK,CAAC;QACrD,OAAO,GAAG,eAAe,CAAC,OAAO,IAAI,IAAI,CAAC;QAC1C,KAAK,GAAG,eAAe,CAAC,KAAK,IAAI,KAAK,CAAC;IAC3C,CAAC;SAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC5D,YAAY,GAAG,SAAS,CAAC;QACzB,eAAe,GAAG,QAAQ,CAAC;QAC3B,YAAY,GAAG,KAAK,CAAC;QACrB,OAAO,GAAG,IAAI,CAAC;QACf,KAAK,GAAG,KAAK,CAAC;IAClB,CAAC;SAAM,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,YAAY,GAAG,OAAO,CAAC;QACvB,eAAe,GAAG,QAAQ,CAAC;QAC3B,YAAY,GAAG,KAAK,CAAC;QACrB,OAAO,GAAG,IAAI,CAAC;QACf,KAAK,GAAG,KAAK,CAAC;IAClB,CAAC;SAAM,CAAC;QACJ,YAAY,GAAG,OAAO,CAAC;QACvB,eAAe,GAAG,OAAO,CAAC;QAC1B,YAAY,GAAG,KAAK,CAAC;QACrB,OAAO,GAAG,IAAI,CAAC;QACf,KAAK,GAAG,KAAK,CAAC;IAClB,CAAC;IAED,oDAAoD;IACpD,mFAAmF;IACnF,yEAAyE;IACzE,uEAAuE;IACvE,MAAM,mBAAmB,GAAG,CAAC,CAAC,eAAe,EAAE,aAAa,CAAC;IAC7D,MAAM,WAAW,GAAG,eAAe,EAAE,aAAa,IAAI,EAAE,CAAC;IAEzD,2CAA2C;IAC3C,MAAM,UAAU,GAAG,eAAe,EAAE,MAAM;QACtC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC;QACxC,CAAC,CAAC,EAAE,CAAC;IAET,MAAM,mBAAmB,GAAG,eAAe,EAAE,eAAe;QACxD,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,eAAe,CAAC;QACjD,CAAC,CAAC,EAAE,CAAC;IAET,OAAO;;;;;;;;;;;;;;;;;UAiBD,UAAU,IAAI;;;;UAId;;;;UAIA,mBAAmB,IAAI;;;;UAIvB;;;;4BAIkB,YAAY;+BACT,eAAe;4BAClB,YAAY;uBACjB,OAAO;oBACV,KAAK;;;;;;;;;;;;yBAYA,mBAAmB,CAAC,CAAC,CAAC,IAAI,WAAW,GAAG,CAAC,CAAC,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkHnF,CAAC;AACF,CAAC,CAAC"}
1
+ {"version":3,"file":"ua-ch.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/ua-ch.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"webgl-spoofing.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgl-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,yBAAyB,sBAAuB,WAAW,KAAG,MAwQ1E,CAAC"}
1
+ {"version":3,"file":"webgl-spoofing.d.ts","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgl-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,WAAW;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,yBAAyB,sBAAuB,WAAW,KAAG,MA2R1E,CAAC"}
@@ -56,16 +56,35 @@ export const createWebGLSpoofingScript = (fingerprintWebGL) => {
56
56
  ],
57
57
  },
58
58
  'MacIntel': {
59
- vendors: ['Google Inc. (Apple)', 'Google Inc. (Intel)', 'Google Inc. (AMD)'],
59
+ // Modern Mac population is overwhelmingly Apple Silicon. Intel and
60
+ // AMD discrete-GPU Macs (2018-2020) are rare in 2026; including them
61
+ // creates a much wider hash distribution than reality and the
62
+ // discrete-GPU strings imply Metal hardware that can't match the
63
+ // SwiftShader-rendered pixels we actually produce. Pin to Apple
64
+ // Silicon variants so the spoofed renderer string and the actual
65
+ // rendering backend stay closer aligned.
66
+ vendors: ['Google Inc. (Apple)'],
60
67
  renderers: [
68
+ 'ANGLE (Apple, Apple M1, OpenGL 4.1)',
61
69
  'ANGLE (Apple, Apple M1 Pro, OpenGL 4.1)',
70
+ 'ANGLE (Apple, Apple M1 Max, OpenGL 4.1)',
62
71
  'ANGLE (Apple, Apple M2, OpenGL 4.1)',
63
- 'ANGLE (Intel Inc., Intel(R) Iris(TM) Plus Graphics OpenGL Engine, OpenGL 4.1)',
64
- 'ANGLE (AMD, AMD Radeon Pro 5500M OpenGL Engine, OpenGL 4.1)',
72
+ 'ANGLE (Apple, Apple M2 Pro, OpenGL 4.1)',
73
+ 'ANGLE (Apple, Apple M2 Max, OpenGL 4.1)',
74
+ 'ANGLE (Apple, Apple M3, OpenGL 4.1)',
75
+ 'ANGLE (Apple, Apple M3 Pro, OpenGL 4.1)',
76
+ 'ANGLE (Apple, Apple M3 Max, OpenGL 4.1)',
77
+ 'ANGLE (Apple, Apple M4, OpenGL 4.1)',
78
+ 'ANGLE (Apple, Apple M4 Pro, OpenGL 4.1)',
65
79
  ],
66
80
  vendorPairs: [
81
+ { vendor: 'Google Inc. (Apple)', renderer: 'ANGLE (Apple, Apple M1, OpenGL 4.1)' },
67
82
  { vendor: 'Google Inc. (Apple)', renderer: 'ANGLE (Apple, Apple M1 Pro, OpenGL 4.1)' },
68
- { vendor: 'Google Inc. (Intel)', renderer: 'ANGLE (Intel Inc., Intel(R) Iris(TM) Plus Graphics OpenGL Engine, OpenGL 4.1)' },
83
+ { vendor: 'Google Inc. (Apple)', renderer: 'ANGLE (Apple, Apple M2, OpenGL 4.1)' },
84
+ { vendor: 'Google Inc. (Apple)', renderer: 'ANGLE (Apple, Apple M2 Pro, OpenGL 4.1)' },
85
+ { vendor: 'Google Inc. (Apple)', renderer: 'ANGLE (Apple, Apple M3, OpenGL 4.1)' },
86
+ { vendor: 'Google Inc. (Apple)', renderer: 'ANGLE (Apple, Apple M3 Pro, OpenGL 4.1)' },
87
+ { vendor: 'Google Inc. (Apple)', renderer: 'ANGLE (Apple, Apple M4, OpenGL 4.1)' },
69
88
  ],
70
89
  },
71
90
  'Linux x86_64': {
@@ -162,7 +181,7 @@ export const createWebGLSpoofingScript = (fingerprintWebGL) => {
162
181
  // Override getShaderPrecisionFormat to prevent GPU cross-referencing.
163
182
  // Anti-bot scripts can compare precision values against the claimed GPU/platform.
164
183
  // These values match the standard IEEE 754 precision formats reported by modern
165
- // D3D11/Metal/Vulkan drivers — consistent across NVIDIA, AMD, and Intel GPUs.
184
+ // D3D11/Metal/Vulkan drivers - consistent across NVIDIA, AMD, and Intel GPUs.
166
185
  const _shaderPrecision = {
167
186
  35633: { // VERTEX_SHADER
168
187
  36336: { rangeMin: 1, rangeMax: 1, precision: 8 }, // LOW_FLOAT
@@ -187,7 +206,7 @@ export const createWebGLSpoofingScript = (fingerprintWebGL) => {
187
206
  const fmt = shaderFmts && shaderFmts[precisionType];
188
207
  if (fmt) {
189
208
  // Return a plain object that mirrors WebGLShaderPrecisionFormat fields.
190
- // Anti-bot scripts read .rangeMin/.rangeMax/.precision — instanceof is not checked.
209
+ // Anti-bot scripts read .rangeMin/.rangeMax/.precision - instanceof is not checked.
191
210
  return { rangeMin: fmt.rangeMin, rangeMax: fmt.rangeMax, precision: fmt.precision };
192
211
  }
193
212
  return _origGetShaderPrecisionFormat.apply(this, arguments);
@@ -1 +1 @@
1
- {"version":3,"file":"webgl-spoofing.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgl-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,gBAA8B,EAAU,EAAE;IAChF,iFAAiF;IACjF,MAAM,cAAc,GAAG,gBAAgB,IAAI,CAAC,gBAAgB,CAAC,cAAc,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAElH,OAAO;;;;;;;;;;UAUD,cAAc,CAAC,CAAC,CAAC;;oCAES,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;;;;SAI3D,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAuFH;;;;;;;;;;;;;;;;;;;yBAmBgB,cAAc,IAAI,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,UAAU;;;yBAGxF,cAAc,IAAI,gBAAgB,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAgFjH,CAAC,cAAc,CAAC,CAAC,CAAC;;;;;;;;;SASnB,CAAC,CAAC,CAAC;;SAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA2CH,CAAC;AACP,CAAC,CAAC"}
1
+ {"version":3,"file":"webgl-spoofing.js","sourceRoot":"","sources":["../../../src/fingerprinting/fingerprint-overrides/webgl-spoofing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,gBAA8B,EAAU,EAAE;IAChF,iFAAiF;IACjF,MAAM,cAAc,GAAG,gBAAgB,IAAI,CAAC,gBAAgB,CAAC,cAAc,IAAI,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;IAElH,OAAO;;;;;;;;;;UAUD,cAAc,CAAC,CAAC,CAAC;;oCAES,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;;;;SAI3D,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SA0GH;;;;;;;;;;;;;;;;;;;yBAmBgB,cAAc,IAAI,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,UAAU;;;yBAGxF,cAAc,IAAI,gBAAgB,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAgFjH,CAAC,cAAc,CAAC,CAAC,CAAC;;;;;;;;;SASnB,CAAC,CAAC,CAAC;;SAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA2CH,CAAC;AACP,CAAC,CAAC"}
@@ -60,7 +60,7 @@ export const createWebRTCSpoofingScript = () => {
60
60
  if (!candidateStr) return candidateStr;
61
61
  // Match private/local IPs (10.x, 172.16-31.x, 192.168.x, fd00::/8, fe80::/10)
62
62
  return candidateStr
63
- .replace(/(?:(?:10|127)\.\\d{1,3}|192\\.168|172\\.(?:1[6-9]|2\\d|3[01]))(?:\\.\\d{1,3}){2}/g, '0.0.0.0')
63
+ .replace(/(?:(?:10|127)\\.\\d{1,3}|192\\.168|172\\.(?:1[6-9]|2\\d|3[01]))(?:\\.\\d{1,3}){2}/g, '0.0.0.0')
64
64
  .replace(/[0-9a-f]{1,4}(?::[0-9a-f]{1,4}){7}/gi, (match) => {
65
65
  if (match.startsWith('fd') || match.startsWith('fe80')) return '0.0.0.0';
66
66
  return match;
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Hardware- and OS-realism helpers shared by BOTH injection paths.
3
+ *
4
+ * The native (C++ FingerprintConfig) path and the JS-injection path each used
5
+ * to carry their own copy of these decisions, and they disagreed - which is how
6
+ * issue #137 happened:
7
+ *
8
+ * - The native path fell back to a macOS platform version on LINUX profiles,
9
+ * because 90% of the harvested Linux pool rows carry no platform version and
10
+ * the fallback was a bare "15.0.0". A Linux Chrome reporting a Sequoia
11
+ * version is a contradiction on its own, and the JS path meanwhile used
12
+ * kernel-shaped values for Linux, so the two paths also disagreed with each
13
+ * other.
14
+ * - The native path resampled the pool's implausible `deviceMemory` values
15
+ * (0 / 1 / 2 / 4 GB on machines that have never shipped with less than 8);
16
+ * the JS path baked the raw value into the page, and because `0` is falsy it
17
+ * skipped the override entirely and leaked the HOST's real RAM.
18
+ * - The storage quota was derived from the RAW pool memory while the page
19
+ * reported the resampled value, so a session could claim 32 GB of RAM with a
20
+ * 1 GB machine's disk quota.
21
+ *
22
+ * Everything here is a pure function of (seed, input), so both paths produce the
23
+ * same values for the same session and the whole surface stays coherent.
24
+ */
25
+ /**
26
+ * UA-CH `platformVersion` candidates per `navigator.platform`.
27
+ *
28
+ * - **Linux** is the empty string. Chromium's `GetPlatformVersion()`
29
+ * (components/embedder_support/user_agent_utils.cc) returns `std::string()` on
30
+ * Linux once the platform-version reduction is enabled, and the harvested pool
31
+ * corroborates it: 90% of real Linux rows carry no platform version at all.
32
+ * Never a version number here, and never a macOS one.
33
+ * - **macOS** is Tahoe-era. Measured on a real macOS host running Chrome 150:
34
+ * `sec-ch-ua-platform-version: "26.3.0"`. The pool agrees, with 57% of mac
35
+ * rows on 26.x. Repeats weight the distribution toward the current release.
36
+ * - **Windows** keeps the UA-CH reduced mapping, which is overwhelmingly 15.0.0
37
+ * for Windows 11 with a small tail at 14.0.0.
38
+ */
39
+ export declare const PLATFORM_VERSION_CANDIDATES: Readonly<Record<string, readonly string[]>>;
40
+ /**
41
+ * Resolve the UA-CH `platformVersion` for a platform, deterministically per
42
+ * seed. Both injection paths call this, so the JS override, the native config
43
+ * and the `sec-ch-ua-platform-version` header cannot disagree.
44
+ */
45
+ export declare function resolvePlatformVersion(platform: string | undefined, seed: number): string;
46
+ /**
47
+ * Pick a `navigator.deviceMemory` that a real machine of this class would
48
+ * report. Plausible upstream values pass through untouched; the pool's legacy
49
+ * spec-bucketed values (≤ 8 GB, including 0) are resampled from
50
+ * `MEMORY_DISTRIBUTION`.
51
+ *
52
+ * Guaranteed to return at least 8, so no caller can end up with a falsy value -
53
+ * that is what silently disabled the JS-path override and leaked the host's RAM.
54
+ */
55
+ export declare function deriveRealisticDeviceMemory(seed: number, rawFromFingerprint: number | undefined): number;
56
+ /**
57
+ * `navigator.storage.estimate().quota`, pinned per session so the host's real
58
+ * disk never leaks and so the same profile reports the same quota on every host.
59
+ *
60
+ * MUST be called with the memory value we actually report, not the raw pool
61
+ * value - the point is coherence between the two. Chrome's StorageManager
62
+ * reports roughly 60% of total disk space; the ±10% seed-driven jitter keeps
63
+ * different sessions from sharing one quota.
64
+ */
65
+ export declare function deriveStorageQuota(seed: number, deviceMemoryGB: number): number;
66
+ /**
67
+ * Stable non-negative hash of a session key, for paths that hold a seed STRING
68
+ * (the JS injector's proxy session key) rather than the numeric seed the native
69
+ * config generator computes. Math-only so the no-bitwise lint rule stays happy.
70
+ */
71
+ export declare function stableSeedFromString(key: string): number;
72
+ /**
73
+ * The platform version to advertise for a profile: the profile's own value when
74
+ * it has a usable one, otherwise a seeded candidate - except on Linux, where the
75
+ * answer is always the empty string.
76
+ *
77
+ * Linux is unconditional because the profile cannot be trusted there: 10% of the
78
+ * harvested Linux rows carry a kernel-shaped version (6.x) from before Chrome
79
+ * reduced the Linux platform version, and advertising one today announces a
80
+ * value current Chrome never sends.
81
+ */
82
+ export declare function normalizePlatformVersion(platform: string | undefined, profileValue: string | undefined, seed: number): string;
83
+ //# sourceMappingURL=hardware-realism.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hardware-realism.d.ts","sourceRoot":"","sources":["../../src/fingerprinting/hardware-realism.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA0BH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,2BAA2B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAInF,CAAC;AAKF;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAKzF;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CASxG;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAe/E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACpC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,IAAI,EAAE,MAAM,GACb,MAAM,CAOR"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Hardware- and OS-realism helpers shared by BOTH injection paths.
3
+ *
4
+ * The native (C++ FingerprintConfig) path and the JS-injection path each used
5
+ * to carry their own copy of these decisions, and they disagreed - which is how
6
+ * issue #137 happened:
7
+ *
8
+ * - The native path fell back to a macOS platform version on LINUX profiles,
9
+ * because 90% of the harvested Linux pool rows carry no platform version and
10
+ * the fallback was a bare "15.0.0". A Linux Chrome reporting a Sequoia
11
+ * version is a contradiction on its own, and the JS path meanwhile used
12
+ * kernel-shaped values for Linux, so the two paths also disagreed with each
13
+ * other.
14
+ * - The native path resampled the pool's implausible `deviceMemory` values
15
+ * (0 / 1 / 2 / 4 GB on machines that have never shipped with less than 8);
16
+ * the JS path baked the raw value into the page, and because `0` is falsy it
17
+ * skipped the override entirely and leaked the HOST's real RAM.
18
+ * - The storage quota was derived from the RAW pool memory while the page
19
+ * reported the resampled value, so a session could claim 32 GB of RAM with a
20
+ * 1 GB machine's disk quota.
21
+ *
22
+ * Everything here is a pure function of (seed, input), so both paths produce the
23
+ * same values for the same session and the whole surface stays coherent.
24
+ */
25
+ /**
26
+ * Memory sizes a real consumer machine reports. Chrome on desktop no longer
27
+ * clamps `navigator.deviceMemory` to the legacy W3C spec buckets - it reports
28
+ * the raw host RAM in GB (verified against a real Chrome on a 32 GB Mac, which
29
+ * reports 32). The upstream fingerprint pool still carries the old capped
30
+ * values, so anything at or below 8 is resampled.
31
+ */
32
+ const PLAUSIBLE_RAW_MEMORY = new Set([16, 24, 32, 48, 64, 96, 128]);
33
+ /**
34
+ * Cumulative-weight table over a realistic 2026 consumer RAM distribution. 8 GB
35
+ * survives as a minority (older Apple Silicon and budget PCs) - Apple's base
36
+ * configuration has been 16 GB since the M4 generation.
37
+ */
38
+ const MEMORY_DISTRIBUTION = [
39
+ [8, 15],
40
+ [16, 55],
41
+ [24, 70],
42
+ [32, 90],
43
+ [48, 95],
44
+ [64, 99],
45
+ [128, 100],
46
+ ];
47
+ /**
48
+ * UA-CH `platformVersion` candidates per `navigator.platform`.
49
+ *
50
+ * - **Linux** is the empty string. Chromium's `GetPlatformVersion()`
51
+ * (components/embedder_support/user_agent_utils.cc) returns `std::string()` on
52
+ * Linux once the platform-version reduction is enabled, and the harvested pool
53
+ * corroborates it: 90% of real Linux rows carry no platform version at all.
54
+ * Never a version number here, and never a macOS one.
55
+ * - **macOS** is Tahoe-era. Measured on a real macOS host running Chrome 150:
56
+ * `sec-ch-ua-platform-version: "26.3.0"`. The pool agrees, with 57% of mac
57
+ * rows on 26.x. Repeats weight the distribution toward the current release.
58
+ * - **Windows** keeps the UA-CH reduced mapping, which is overwhelmingly 15.0.0
59
+ * for Windows 11 with a small tail at 14.0.0.
60
+ */
61
+ export const PLATFORM_VERSION_CANDIDATES = {
62
+ 'Win32': ['15.0.0', '15.0.0', '15.0.0', '14.0.0'],
63
+ 'MacIntel': ['26.3.0', '26.3.0', '26.2.0', '26.1.0', '26.0.0', '15.6.0', '15.5.0'],
64
+ 'Linux x86_64': [''],
65
+ };
66
+ /** Platform used when the requested one is unknown - desktop Windows dominates the population. */
67
+ const PLATFORM_VERSION_FALLBACK_KEY = 'Win32';
68
+ /**
69
+ * Resolve the UA-CH `platformVersion` for a platform, deterministically per
70
+ * seed. Both injection paths call this, so the JS override, the native config
71
+ * and the `sec-ch-ua-platform-version` header cannot disagree.
72
+ */
73
+ export function resolvePlatformVersion(platform, seed) {
74
+ const candidates = PLATFORM_VERSION_CANDIDATES[platform ?? '']
75
+ ?? PLATFORM_VERSION_CANDIDATES[PLATFORM_VERSION_FALLBACK_KEY];
76
+ const index = Math.abs(Math.trunc(Number.isFinite(seed) ? seed : 0)) % candidates.length;
77
+ return candidates[index];
78
+ }
79
+ /**
80
+ * Pick a `navigator.deviceMemory` that a real machine of this class would
81
+ * report. Plausible upstream values pass through untouched; the pool's legacy
82
+ * spec-bucketed values (≤ 8 GB, including 0) are resampled from
83
+ * `MEMORY_DISTRIBUTION`.
84
+ *
85
+ * Guaranteed to return at least 8, so no caller can end up with a falsy value -
86
+ * that is what silently disabled the JS-path override and leaked the host's RAM.
87
+ */
88
+ export function deriveRealisticDeviceMemory(seed, rawFromFingerprint) {
89
+ if (typeof rawFromFingerprint === 'number' && PLAUSIBLE_RAW_MEMORY.has(rawFromFingerprint)) {
90
+ return rawFromFingerprint;
91
+ }
92
+ const pick = Math.abs(Math.trunc(Number.isFinite(seed) ? seed : 0)) % 100;
93
+ for (const [gb, cumulative] of MEMORY_DISTRIBUTION) {
94
+ if (pick < cumulative)
95
+ return gb;
96
+ }
97
+ return 16;
98
+ }
99
+ /**
100
+ * `navigator.storage.estimate().quota`, pinned per session so the host's real
101
+ * disk never leaks and so the same profile reports the same quota on every host.
102
+ *
103
+ * MUST be called with the memory value we actually report, not the raw pool
104
+ * value - the point is coherence between the two. Chrome's StorageManager
105
+ * reports roughly 60% of total disk space; the ±10% seed-driven jitter keeps
106
+ * different sessions from sharing one quota.
107
+ */
108
+ export function deriveStorageQuota(seed, deviceMemoryGB) {
109
+ // eslint-disable-next-line no-bitwise -- low bit selects between two SSD sizes
110
+ const lowBit = seed & 1;
111
+ let ssdSizeGB;
112
+ if (deviceMemoryGB <= 8) {
113
+ ssdSizeGB = lowBit ? 256 : 512;
114
+ }
115
+ else if (deviceMemoryGB <= 16) {
116
+ ssdSizeGB = lowBit ? 512 : 1024;
117
+ }
118
+ else {
119
+ ssdSizeGB = lowBit ? 1024 : 2048;
120
+ }
121
+ // eslint-disable-next-line no-bitwise -- byte 1 of the seed drives the jitter
122
+ const jitterFraction = (((seed >>> 8) & 0xFF) / 255) * 0.2 - 0.1;
123
+ const totalBytes = ssdSizeGB * 1024 * 1024 * 1024;
124
+ return Math.floor(totalBytes * (0.60 + jitterFraction));
125
+ }
126
+ /**
127
+ * Stable non-negative hash of a session key, for paths that hold a seed STRING
128
+ * (the JS injector's proxy session key) rather than the numeric seed the native
129
+ * config generator computes. Math-only so the no-bitwise lint rule stays happy.
130
+ */
131
+ export function stableSeedFromString(key) {
132
+ let hash = 0x811C9DC5;
133
+ for (let i = 0; i < key.length; i++) {
134
+ hash = (hash * 31 + key.charCodeAt(i)) % 0x7FFFFFFF;
135
+ }
136
+ return hash;
137
+ }
138
+ /**
139
+ * The platform version to advertise for a profile: the profile's own value when
140
+ * it has a usable one, otherwise a seeded candidate - except on Linux, where the
141
+ * answer is always the empty string.
142
+ *
143
+ * Linux is unconditional because the profile cannot be trusted there: 10% of the
144
+ * harvested Linux rows carry a kernel-shaped version (6.x) from before Chrome
145
+ * reduced the Linux platform version, and advertising one today announces a
146
+ * value current Chrome never sends.
147
+ */
148
+ export function normalizePlatformVersion(platform, profileValue, seed) {
149
+ if (platform === 'Linux x86_64') {
150
+ return '';
151
+ }
152
+ return profileValue && profileValue.length > 0
153
+ ? profileValue
154
+ : resolvePlatformVersion(platform, seed);
155
+ }
156
+ //# sourceMappingURL=hardware-realism.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hardware-realism.js","sourceRoot":"","sources":["../../src/fingerprinting/hardware-realism.ts"],"names":[],"mappings":"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"}