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.
- package/README.md +1 -607
- package/browser/fonts/macos-bundle/40-macos-aliases.conf +515 -0
- package/browser/fonts/macos-bundle/README.md +24 -0
- package/browser/fonts/macos-bundle/install.sh +83 -0
- package/dist/browser-controller.d.ts +47 -4
- package/dist/browser-controller.d.ts.map +1 -1
- package/dist/browser-controller.js +219 -278
- package/dist/browser-controller.js.map +1 -1
- package/dist/browser-plugin.d.ts +82 -110
- package/dist/browser-plugin.d.ts.map +1 -1
- package/dist/browser-plugin.js +376 -379
- package/dist/browser-plugin.js.map +1 -1
- package/dist/browser-process/align-fingerprint-config.d.ts +36 -0
- package/dist/browser-process/align-fingerprint-config.d.ts.map +1 -0
- package/dist/browser-process/align-fingerprint-config.js +74 -0
- package/dist/browser-process/align-fingerprint-config.js.map +1 -0
- package/dist/browser-process/anti-detect-browser.d.ts +2 -2
- package/dist/browser-process/anti-detect-browser.js +7 -7
- package/dist/browser-process/anti-detect-config.d.ts +131 -2
- package/dist/browser-process/anti-detect-config.d.ts.map +1 -1
- package/dist/browser-process/anti-detect-config.js +337 -127
- package/dist/browser-process/anti-detect-config.js.map +1 -1
- package/dist/browser-process/browser.d.ts +25 -92
- package/dist/browser-process/browser.d.ts.map +1 -1
- package/dist/browser-process/browser.js +429 -73
- package/dist/browser-process/browser.js.map +1 -1
- package/dist/browser-process/fingerprint-config.d.ts +146 -0
- package/dist/browser-process/fingerprint-config.d.ts.map +1 -0
- package/dist/browser-process/fingerprint-config.js +308 -0
- package/dist/browser-process/fingerprint-config.js.map +1 -0
- package/dist/browser-process/get-chrome-executable.d.ts +6 -0
- package/dist/browser-process/get-chrome-executable.d.ts.map +1 -1
- package/dist/browser-process/get-chrome-executable.js +79 -4
- package/dist/browser-process/get-chrome-executable.js.map +1 -1
- package/dist/browser-process/gpu-family-profiles.d.ts +58 -0
- package/dist/browser-process/gpu-family-profiles.d.ts.map +1 -0
- package/dist/browser-process/gpu-family-profiles.js +480 -0
- package/dist/browser-process/gpu-family-profiles.js.map +1 -0
- package/dist/browser-process/launch-options.d.ts +301 -0
- package/dist/browser-process/launch-options.d.ts.map +1 -0
- package/dist/browser-process/launch-options.js +2 -0
- package/dist/browser-process/launch-options.js.map +1 -0
- package/dist/browser-process/port-allocator.d.ts +64 -0
- package/dist/browser-process/port-allocator.d.ts.map +1 -0
- package/dist/browser-process/port-allocator.js +198 -0
- package/dist/browser-process/port-allocator.js.map +1 -0
- package/dist/browser-process/process.d.ts +85 -0
- package/dist/browser-process/process.d.ts.map +1 -1
- package/dist/browser-process/process.js +235 -19
- package/dist/browser-process/process.js.map +1 -1
- package/dist/browser-process/signal-cleanup.d.ts +40 -0
- package/dist/browser-process/signal-cleanup.d.ts.map +1 -0
- package/dist/browser-process/signal-cleanup.js +105 -0
- package/dist/browser-process/signal-cleanup.js.map +1 -0
- package/dist/browser-process/widevine-cdm.d.ts +144 -0
- package/dist/browser-process/widevine-cdm.d.ts.map +1 -0
- package/dist/browser-process/widevine-cdm.js +298 -0
- package/dist/browser-process/widevine-cdm.js.map +1 -0
- package/dist/browser-profiles/chrome/populate-profile.d.ts.map +1 -1
- package/dist/browser-profiles/chrome/populate-profile.js +21 -22
- package/dist/browser-profiles/chrome/populate-profile.js.map +1 -1
- package/dist/connection/cdp-reconnection.d.ts +50 -0
- package/dist/connection/cdp-reconnection.d.ts.map +1 -0
- package/dist/connection/cdp-reconnection.js +75 -0
- package/dist/connection/cdp-reconnection.js.map +1 -0
- package/dist/connection/page-session.d.ts +114 -0
- package/dist/connection/page-session.d.ts.map +1 -0
- package/dist/connection/page-session.js +237 -0
- package/dist/connection/page-session.js.map +1 -0
- package/dist/connection/session-client.d.ts +34 -0
- package/dist/connection/session-client.d.ts.map +1 -0
- package/dist/connection/session-client.js +129 -0
- package/dist/connection/session-client.js.map +1 -0
- package/dist/crawler.d.ts +9 -88
- package/dist/crawler.d.ts.map +1 -1
- package/dist/crawler.js +157 -8
- package/dist/crawler.js.map +1 -1
- package/dist/fingerprinting/fingerprint-injector.d.ts +24 -114
- package/dist/fingerprinting/fingerprint-injector.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-injector.js +305 -611
- package/dist/fingerprinting/fingerprint-injector.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts +1 -1
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js +16 -14
- package/dist/fingerprinting/fingerprint-overrides/datadome-bypass.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/index.d.ts +6 -2
- package/dist/fingerprinting/fingerprint-overrides/index.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/index.js +6 -2
- package/dist/fingerprinting/fingerprint-overrides/index.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.d.ts +1 -1
- package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js +4 -4
- package/dist/fingerprinting/fingerprint-overrides/keyboard-humanization.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/locale-spoofing.js +4 -4
- package/dist/fingerprinting/fingerprint-overrides/navigator-override.d.ts +18 -0
- package/dist/fingerprinting/fingerprint-overrides/navigator-override.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/navigator-override.js +136 -0
- package/dist/fingerprinting/fingerprint-overrides/navigator-override.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/override.d.ts +151 -0
- package/dist/fingerprinting/fingerprint-overrides/override.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/override.js +14 -0
- package/dist/fingerprinting/fingerprint-overrides/override.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js +46 -15
- package/dist/fingerprinting/fingerprint-overrides/platform-consistency.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/registry.d.ts +43 -0
- package/dist/fingerprinting/fingerprint-overrides/registry.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/registry.js +342 -0
- package/dist/fingerprinting/fingerprint-overrides/registry.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/screen-override.d.ts +16 -0
- package/dist/fingerprinting/fingerprint-overrides/screen-override.d.ts.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/screen-override.js +175 -0
- package/dist/fingerprinting/fingerprint-overrides/screen-override.js.map +1 -0
- package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.d.ts +1 -1
- package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js +4 -4
- package/dist/fingerprinting/fingerprint-overrides/scroll-humanization.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.js +75 -9
- package/dist/fingerprinting/fingerprint-overrides/stealth-script.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts +1 -1
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.js +34 -20
- package/dist/fingerprinting/fingerprint-overrides/ua-ch.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.d.ts.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js +25 -6
- package/dist/fingerprinting/fingerprint-overrides/webgl-spoofing.js.map +1 -1
- package/dist/fingerprinting/fingerprint-overrides/webrtc-spoofing.js +1 -1
- package/dist/fingerprinting/hardware-realism.d.ts +83 -0
- package/dist/fingerprinting/hardware-realism.d.ts.map +1 -0
- package/dist/fingerprinting/hardware-realism.js +156 -0
- package/dist/fingerprinting/hardware-realism.js.map +1 -0
- package/dist/fingerprinting/injection-planner.d.ts +133 -0
- package/dist/fingerprinting/injection-planner.d.ts.map +1 -0
- package/dist/fingerprinting/injection-planner.js +497 -0
- package/dist/fingerprinting/injection-planner.js.map +1 -0
- package/dist/fingerprinting/locale-resolver.d.ts +8 -1
- package/dist/fingerprinting/locale-resolver.d.ts.map +1 -1
- package/dist/fingerprinting/locale-resolver.js +26 -3
- package/dist/fingerprinting/locale-resolver.js.map +1 -1
- package/dist/fingerprinting/non-apify-fingerprint-generator.d.ts +4 -4
- package/dist/fingerprinting/non-apify-fingerprint-generator.d.ts.map +1 -1
- package/dist/fingerprinting/non-apify-fingerprint-generator.js +24 -58
- package/dist/fingerprinting/non-apify-fingerprint-generator.js.map +1 -1
- package/dist/fingerprinting/non-apify-profiles.json +10515 -8494
- package/dist/fingerprinting/os-consistency.d.ts +28 -0
- package/dist/fingerprinting/os-consistency.d.ts.map +1 -0
- package/dist/fingerprinting/os-consistency.js +45 -0
- package/dist/fingerprinting/os-consistency.js.map +1 -0
- package/dist/fingerprinting/profile-quality.d.ts +25 -0
- package/dist/fingerprinting/profile-quality.d.ts.map +1 -0
- package/dist/fingerprinting/profile-quality.js +310 -0
- package/dist/fingerprinting/profile-quality.js.map +1 -0
- package/dist/fingerprinting/profile-selector.d.ts +102 -0
- package/dist/fingerprinting/profile-selector.d.ts.map +1 -0
- package/dist/fingerprinting/profile-selector.js +168 -0
- package/dist/fingerprinting/profile-selector.js.map +1 -0
- package/dist/fingerprinting/ua-alignment.d.ts +83 -0
- package/dist/fingerprinting/ua-alignment.d.ts.map +1 -0
- package/dist/fingerprinting/ua-alignment.js +197 -0
- package/dist/fingerprinting/ua-alignment.js.map +1 -0
- package/dist/fingerprinting/ua-ch-brands.d.ts +88 -0
- package/dist/fingerprinting/ua-ch-brands.d.ts.map +1 -0
- package/dist/fingerprinting/ua-ch-brands.js +174 -0
- package/dist/fingerprinting/ua-ch-brands.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/input/dropdown-selector.d.ts +90 -0
- package/dist/input/dropdown-selector.d.ts.map +1 -0
- package/dist/input/dropdown-selector.js +394 -0
- package/dist/input/dropdown-selector.js.map +1 -0
- package/dist/input/element-target.d.ts +152 -0
- package/dist/input/element-target.d.ts.map +1 -0
- package/dist/input/element-target.js +461 -0
- package/dist/input/element-target.js.map +1 -0
- package/dist/input/input-emulator.d.ts +85 -0
- package/dist/input/input-emulator.d.ts.map +1 -0
- package/dist/input/input-emulator.js +325 -0
- package/dist/input/input-emulator.js.map +1 -0
- package/dist/input/input-transport.d.ts +60 -0
- package/dist/input/input-transport.d.ts.map +1 -0
- package/dist/input/input-transport.js +28 -0
- package/dist/input/input-transport.js.map +1 -0
- package/dist/input/recording-transport.d.ts +32 -0
- package/dist/input/recording-transport.d.ts.map +1 -0
- package/dist/input/recording-transport.js +43 -0
- package/dist/input/recording-transport.js.map +1 -0
- package/dist/keyboard-layout.d.ts +2 -2
- package/dist/keyboard-layout.js +2 -2
- package/dist/navigation/page-navigation.d.ts +67 -0
- package/dist/navigation/page-navigation.d.ts.map +1 -0
- package/dist/navigation/page-navigation.js +122 -0
- package/dist/navigation/page-navigation.js.map +1 -0
- package/dist/network/network-watch.d.ts +110 -0
- package/dist/network/network-watch.d.ts.map +1 -0
- package/dist/network/network-watch.js +223 -0
- package/dist/network/network-watch.js.map +1 -0
- package/dist/page.d.ts +118 -104
- package/dist/page.d.ts.map +1 -1
- package/dist/page.js +311 -1130
- package/dist/page.js.map +1 -1
- package/dist/session/inject-hook.d.ts +24 -0
- package/dist/session/inject-hook.d.ts.map +1 -0
- package/dist/session/inject-hook.js +80 -0
- package/dist/session/inject-hook.js.map +1 -0
- package/dist/session/save.d.ts +21 -0
- package/dist/session/save.d.ts.map +1 -0
- package/dist/session/save.js +163 -0
- package/dist/session/save.js.map +1 -0
- package/dist/session/tar-data-dir.d.ts +18 -0
- package/dist/session/tar-data-dir.d.ts.map +1 -0
- package/dist/session/tar-data-dir.js +105 -0
- package/dist/session/tar-data-dir.js.map +1 -0
- package/dist/session/types.d.ts +80 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +29 -0
- package/dist/session/types.js.map +1 -0
- package/dist/session-profile.d.ts +102 -0
- package/dist/session-profile.d.ts.map +1 -0
- package/dist/session-profile.js +163 -0
- package/dist/session-profile.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +17 -6
- package/scripts/postinstall.cjs +58 -0
- package/dist/fingerprinting/custom-fingerprint-injector.d.ts +0 -87
- package/dist/fingerprinting/custom-fingerprint-injector.d.ts.map +0 -1
- package/dist/fingerprinting/custom-fingerprint-injector.js +0 -342
- package/dist/fingerprinting/custom-fingerprint-injector.js.map +0 -1
- package/dist/launcher-wrap.d.ts +0 -10
- package/dist/launcher-wrap.d.ts.map +0 -1
- package/dist/launcher-wrap.js +0 -11
- package/dist/launcher-wrap.js.map +0 -1
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { log } from 'crawlee';
|
|
2
|
+
import { FingerprintGenerator } from 'fingerprint-generator';
|
|
3
|
+
import { generateNonApifyFingerprint } from './non-apify-fingerprint-generator.js';
|
|
4
|
+
import { describeOsConflict } from './os-consistency.js';
|
|
5
|
+
import { rejectContaminatedProfile } from './profile-quality.js';
|
|
6
|
+
import { osHintToPlatform, resolveOsHint, resolveSeedKey, } from '../session-profile.js';
|
|
7
|
+
export const defaultProfilePoolPort = {
|
|
8
|
+
drawNonApify: async (opts) => generateNonApifyFingerprint(opts),
|
|
9
|
+
createApifyReroller: genOpts => new FingerprintGenerator(genOpts),
|
|
10
|
+
};
|
|
11
|
+
/** Key under which callers stamp the selection result onto the launch context. */
|
|
12
|
+
export const PROFILE_SELECTION_KEY = 'profileSelection';
|
|
13
|
+
const NON_APIFY_MAX_ATTEMPTS = 8;
|
|
14
|
+
// The upstream Apify pool's contamination rate for macOS-arm is ~55-60%, so
|
|
15
|
+
// 8 attempts has a ~0.6^8 = 1.7% miss rate but a clean profile may take
|
|
16
|
+
// 15-20 tries when the rejection is hardware-coherence-strict.
|
|
17
|
+
const APIFY_MAX_REROLL_ATTEMPTS = 32;
|
|
18
|
+
/**
|
|
19
|
+
* Pick a clean fingerprint profile for the expected OS.
|
|
20
|
+
*
|
|
21
|
+
* Owns the whole selection protocol: seed-key resolution, OS-pin validation,
|
|
22
|
+
* os-hint expectation, pool choice (Apify synthetic vs non-Apify real-device),
|
|
23
|
+
* and the contamination re-roll loop gated by `rejectContaminatedProfile`.
|
|
24
|
+
*
|
|
25
|
+
* The pool-contamination background: the upstream fingerprint-generator
|
|
26
|
+
* dataset contains a recurring fraction of profiles from Lark/Feishu
|
|
27
|
+
* (ByteDance) modified Chrome installs - see `profile-quality.ts` for the
|
|
28
|
+
* telltales. A contaminated profile flows verbatim into FingerprintConfig and
|
|
29
|
+
* the C++ source-tree overrides dutifully spoof to it, so every
|
|
30
|
+
* CreepJS/DataDome/Naver run sees a bot. We re-roll until clean, capped.
|
|
31
|
+
*
|
|
32
|
+
* When `operatingSystems[0]` and the deprecated `fingerprintOptions.platform`
|
|
33
|
+
* contradict each other, `operatingSystems` wins and a warning is logged (see
|
|
34
|
+
* `describeOsConflict`) - the conflict is no longer fatal (issue #80).
|
|
35
|
+
*/
|
|
36
|
+
export async function selectFingerprintProfile(input, port = defaultProfilePoolPort) {
|
|
37
|
+
const fpOpts = input.fingerprintOptions;
|
|
38
|
+
const fpGenOpts = input.fingerprintGeneratorOptions;
|
|
39
|
+
const seedKey = resolveSeedKey({ proxyUrl: input.proxyUrl, explicitSeedKey: fpOpts?.seedKey });
|
|
40
|
+
const explicitPlatform = fpOpts?.platform;
|
|
41
|
+
// Defense in depth: catches direct CDPBrowserPlugin users who bypass the
|
|
42
|
+
// Crawler constructor. In a Crawler-driven launch crawler.ts has already
|
|
43
|
+
// warned + auto-filled, so this re-check cannot false-positive. Non-fatal:
|
|
44
|
+
// operatingSystems is the single source of truth and wins (issue #80).
|
|
45
|
+
const osConflict = describeOsConflict(fpGenOpts?.operatingSystems?.[0], explicitPlatform);
|
|
46
|
+
if (osConflict)
|
|
47
|
+
log.warning(osConflict);
|
|
48
|
+
// Priority: explicit fingerprintOptions.platform → pinned operatingSystems[0]
|
|
49
|
+
// → the OS of the fingerprint Crawlee already generated → host OS.
|
|
50
|
+
//
|
|
51
|
+
// The generated-fingerprint fallback is load-bearing: BrowserPool generates
|
|
52
|
+
// `launchContext.fingerprint` from its own `fingerprintGeneratorOptions` but
|
|
53
|
+
// does NOT copy those options onto `launchOptions`, so a pool-level OS pin
|
|
54
|
+
// only survives here through the generated fingerprint. We read the UA first
|
|
55
|
+
// and the platform only as a fallback: the upstream pool ships ~2.5% of
|
|
56
|
+
// "windows" draws whose UA + uaData say Windows but whose navigator.platform
|
|
57
|
+
// lies "Linux x86_64". Trusting platform there resolved the OS to linux and
|
|
58
|
+
// the non-Apify pool then drew a genuine Linux profile (issue: Win32 tests
|
|
59
|
+
// flaking to "Linux x86_64"). The UA is the coherent signal.
|
|
60
|
+
const currentNav = input.currentFingerprint?.fingerprint?.navigator;
|
|
61
|
+
const fingerprintUserAgent = currentNav?.userAgent;
|
|
62
|
+
const fingerprintPlatform = currentNav?.platform;
|
|
63
|
+
const expectedOs = resolveOsHint({
|
|
64
|
+
explicitPlatform,
|
|
65
|
+
operatingSystems: fpGenOpts?.operatingSystems,
|
|
66
|
+
fingerprintUserAgent,
|
|
67
|
+
fingerprintPlatform,
|
|
68
|
+
hostPlatform: input.hostPlatform,
|
|
69
|
+
});
|
|
70
|
+
const expectedPlatform = expectedOs ? osHintToPlatform(expectedOs) : null;
|
|
71
|
+
const reject = (fp) => rejectContaminatedProfile(fp, expectedPlatform);
|
|
72
|
+
const base = {
|
|
73
|
+
seedKey,
|
|
74
|
+
expectedOs,
|
|
75
|
+
expectedPlatform,
|
|
76
|
+
};
|
|
77
|
+
if (fpOpts?.useNonApifyFingerprints) {
|
|
78
|
+
// Real-device pool. Host-OS fallback at the end of the chain matches the
|
|
79
|
+
// crawler.ts default-OS policy (exotic hosts pool with Windows).
|
|
80
|
+
const osHint = expectedOs ?? 'windows';
|
|
81
|
+
// When `explicitPlatform` is unset, derive it from `osHint` so the pool's
|
|
82
|
+
// `platformToOs(platform)` mapping (which wins over the `os` field) lands
|
|
83
|
+
// on the same bucket.
|
|
84
|
+
const platformForPool = explicitPlatform ?? osHintToPlatform(osHint);
|
|
85
|
+
let fp = await port.drawNonApify({ platform: platformForPool, os: osHint, proxySeedKey: seedKey });
|
|
86
|
+
let rejection = reject(fp);
|
|
87
|
+
let attempts = 1;
|
|
88
|
+
while (rejection && attempts < NON_APIFY_MAX_ATTEMPTS) {
|
|
89
|
+
log.debug(`[AntiDetect] Rejected non-Apify profile (attempt ${attempts}): ${rejection}`);
|
|
90
|
+
fp = await port.drawNonApify({
|
|
91
|
+
platform: platformForPool,
|
|
92
|
+
os: osHint,
|
|
93
|
+
// Deterministic re-roll: same seed + attempt suffix → same escape path.
|
|
94
|
+
// With no seed key, the pool draw is deterministic per seed, so
|
|
95
|
+
// reusing `null` every attempt would redraw the SAME contaminated
|
|
96
|
+
// profile forever; a synthetic per-attempt seed makes each draw
|
|
97
|
+
// distinct while staying reproducible across runs.
|
|
98
|
+
proxySeedKey: seedKey ? `${seedKey}-r${attempts}` : `reroll-${attempts}`,
|
|
99
|
+
});
|
|
100
|
+
rejection = reject(fp);
|
|
101
|
+
attempts++;
|
|
102
|
+
}
|
|
103
|
+
if (rejection) {
|
|
104
|
+
log.warning(`[AntiDetect] non-Apify profile pool returned contaminated entries for ${NON_APIFY_MAX_ATTEMPTS} attempts; using last: ${rejection}`);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
...base,
|
|
108
|
+
fingerprint: fp,
|
|
109
|
+
rerolls: attempts - 1,
|
|
110
|
+
rejection,
|
|
111
|
+
replaced: true,
|
|
112
|
+
usedNonApifyPool: true,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
// Default Apify synthetic pool - also contains contaminated profiles
|
|
116
|
+
// (LarkUrl / Rambox / newsai / 184-cores / Linux-platform-with-Mac-UA).
|
|
117
|
+
let fp = input.currentFingerprint;
|
|
118
|
+
let rejection = reject(fp);
|
|
119
|
+
let attempts = 1;
|
|
120
|
+
if (rejection) {
|
|
121
|
+
const rerollGenOpts = {
|
|
122
|
+
...(fpGenOpts ?? {}),
|
|
123
|
+
browsers: ['chrome'],
|
|
124
|
+
devices: ['desktop'],
|
|
125
|
+
// When the OS wasn't pinned via fingerprintGeneratorOptions (e.g. it
|
|
126
|
+
// came through BrowserPool-level config instead), constrain the
|
|
127
|
+
// re-roller to the resolved OS - otherwise it pulls host-biased
|
|
128
|
+
// profiles the platform filter then rejects, either shipping a
|
|
129
|
+
// wrong-OS profile or exhausting all attempts.
|
|
130
|
+
...(expectedOs && !fpGenOpts?.operatingSystems
|
|
131
|
+
? { operatingSystems: [expectedOs] }
|
|
132
|
+
: {}),
|
|
133
|
+
};
|
|
134
|
+
const reroller = input.externalGenerator?.getFingerprint
|
|
135
|
+
? input.externalGenerator
|
|
136
|
+
: port.createApifyReroller(rerollGenOpts);
|
|
137
|
+
while (rejection && attempts < APIFY_MAX_REROLL_ATTEMPTS) {
|
|
138
|
+
log.debug(`[AntiDetect] Rejected Apify profile (attempt ${attempts}): ${rejection}`);
|
|
139
|
+
try {
|
|
140
|
+
const next = await reroller.getFingerprint();
|
|
141
|
+
if (!next)
|
|
142
|
+
break;
|
|
143
|
+
fp = next;
|
|
144
|
+
}
|
|
145
|
+
catch (e) {
|
|
146
|
+
log.debug(`[AntiDetect] Re-roll attempt ${attempts} failed: ${e?.message}`);
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
rejection = reject(fp);
|
|
150
|
+
attempts++;
|
|
151
|
+
}
|
|
152
|
+
if (rejection) {
|
|
153
|
+
log.warning(`[AntiDetect] Apify fingerprint pool kept returning contaminated entries after ${attempts - 1} re-rolls; using last: ${rejection}`);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
log.debug(`[AntiDetect] Escaped contaminated pool entry after ${attempts - 1} re-rolls`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
...base,
|
|
161
|
+
fingerprint: fp,
|
|
162
|
+
rerolls: attempts - 1,
|
|
163
|
+
rejection,
|
|
164
|
+
replaced: attempts > 1 && !!fp,
|
|
165
|
+
usedNonApifyPool: false,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=profile-selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-selector.js","sourceRoot":"","sources":["../../src/fingerprinting/profile-selector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UaAlignment - pure functions that align a fingerprint profile's version
|
|
3
|
+
* surfaces (User-Agent string, UA-CH brands/full-version list, the
|
|
4
|
+
* platform-consistency config, and injectable headers) with the version of
|
|
5
|
+
* the binary that is actually running.
|
|
6
|
+
*
|
|
7
|
+
* The fingerprint pool routinely ships profiles a few majors behind the
|
|
8
|
+
* shipped binary (132–135 vs 147+); an unaligned UA contradicts
|
|
9
|
+
* `Browser.getVersion` and every UA-CH surface - an instant detection signal.
|
|
10
|
+
* The injector probes the binary version over CDP and feeds it in here; all
|
|
11
|
+
* the rewriting itself is deterministic string/structure work, unit-testable
|
|
12
|
+
* without a browser.
|
|
13
|
+
*/
|
|
14
|
+
import type { PlatformConfig } from './fingerprint-overrides/platform-consistency.js';
|
|
15
|
+
import type { UAClientHintsData } from './fingerprint-overrides/ua-ch.js';
|
|
16
|
+
/**
|
|
17
|
+
* Re-stamp the Chrome version in a UA string to the running binary's major.
|
|
18
|
+
*
|
|
19
|
+
* Chrome UA Reduction (shipped Chrome 107+) freezes minor/build/patch to
|
|
20
|
+
* 0.0.0 in the User-Agent string - the full build version lives only in
|
|
21
|
+
* UA-CH uaFullVersion. We must use major.0.0.0 here or risk producing a
|
|
22
|
+
* non-existent version string like "Chrome/147.0.7727.56" which is trivially
|
|
23
|
+
* detectable.
|
|
24
|
+
*
|
|
25
|
+
* Direction matters: the UA is always pulled UP to the real binary, never the
|
|
26
|
+
* binary's identity pushed down to the profile's older major. A UA announcing a
|
|
27
|
+
* version the TLS/H2 handshake does not corroborate is itself a hard block -
|
|
28
|
+
* measured on `search.shopping.naver.com`, which refuses a Chrome/147 UA sent
|
|
29
|
+
* over a Chrome 142 handshake (issue #131). The binary is the ground truth
|
|
30
|
+
* every other surface aligns to.
|
|
31
|
+
*/
|
|
32
|
+
export declare function alignUserAgentWithBrowserVersion(userAgent: string, browserVersion: string | null): string;
|
|
33
|
+
/**
|
|
34
|
+
* Align UA-CH brands with the actual running Chrome binary version.
|
|
35
|
+
*
|
|
36
|
+
* Every entry is rewritten, GREASE included. The GREASE token is not bogus
|
|
37
|
+
* padding: Chromium derives its separators, its fake version and the order of
|
|
38
|
+
* the three-entry list from the major version (see `ua-ch-brands.ts`), so a
|
|
39
|
+
* profile's GREASE token is a fingerprint of the major that profile came from.
|
|
40
|
+
* Keeping a Chrome 134 GREASE on a Chrome 147 UA produced a `sec-ch-ua` no
|
|
41
|
+
* Chromium has ever emitted - and a hard, challenge-free HTTP 418 on
|
|
42
|
+
* `search.shopping.naver.com` (issue #131).
|
|
43
|
+
*/
|
|
44
|
+
export declare function alignUAClientHintsVersion(uaClientHints: UAClientHintsData, fullVersion: string): UAClientHintsData;
|
|
45
|
+
/**
|
|
46
|
+
* Platform-consistency config alignment: when using real fingerprint data,
|
|
47
|
+
* align its UA/appVersion with the actual binary version; when using
|
|
48
|
+
* hardcoded defaults, inject a minimal version-aligned UA for any known
|
|
49
|
+
* platform (Win32 / MacIntel / Linux x86_64) so we don't bake in the static
|
|
50
|
+
* Chrome/134.0.0.0 fallback. Returns the input untouched when no platform is
|
|
51
|
+
* requested - so the UA-mismatch warn log doesn't fire for runs that never
|
|
52
|
+
* inject the platform-consistency override.
|
|
53
|
+
*/
|
|
54
|
+
export declare function alignPlatformConfigWithBinary(platformConfig: PlatformConfig | undefined, requestedPlatform: string | undefined, actualChromeVersion: string | null): PlatformConfig | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Filter fingerprint-generator headers down to the set injectable via CDP,
|
|
57
|
+
* apply the resolved Accept-Language (it wins over whatever the generator
|
|
58
|
+
* headers had so `fingerprintOptions.locale: 'ko-KR'` reaches the wire), and
|
|
59
|
+
* stamp the version-aligned User-Agent.
|
|
60
|
+
*
|
|
61
|
+
* `binaryVersion` also rewrites the UA-CH request headers, which
|
|
62
|
+
* `Network.setExtraHTTPHeaders` puts on the wire ABOVE whatever the
|
|
63
|
+
* `setUserAgentOverride` metadata would have produced. Forwarding the
|
|
64
|
+
* generator's copy verbatim shipped three separate contradictions (issue #131):
|
|
65
|
+
*
|
|
66
|
+
* - the profile's ORIGINAL major next to an aligned User-Agent;
|
|
67
|
+
* - a GREASE token from that original major;
|
|
68
|
+
* - a third-party brand - 44 of the 200 bundled non-Apify rows carry a
|
|
69
|
+
* `sec-ch-ua` header advertising **Brave** while their JS-side
|
|
70
|
+
* `userAgentData.brands` says Google Chrome. The brand-cohort gate only
|
|
71
|
+
* inspected the JS side, so the header walked straight past it.
|
|
72
|
+
*
|
|
73
|
+
* So `sec-ch-ua` is rebuilt from scratch - the canonical list a real Chrome of
|
|
74
|
+
* this binary emits - rather than aligned in place.
|
|
75
|
+
* `sec-ch-ua-full-version-list` is dropped instead of rewritten: it is a
|
|
76
|
+
* high-entropy hint that real Chrome sends only after an origin asks via
|
|
77
|
+
* `accept-ch`, so forcing it onto every request is itself a tell. Chrome emits
|
|
78
|
+
* it from the UA metadata when it is actually requested.
|
|
79
|
+
*
|
|
80
|
+
* Omit the argument (or pass null) to leave the headers alone.
|
|
81
|
+
*/
|
|
82
|
+
export declare function buildInjectableHeaders(headers: Record<string, string>, resolvedLanguages: string | undefined, alignedUserAgent: string, binaryVersion?: string | null): Record<string, string>;
|
|
83
|
+
//# sourceMappingURL=ua-alignment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ua-alignment.d.ts","sourceRoot":"","sources":["../../src/fingerprinting/ua-alignment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iDAAiD,CAAC;AACtF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAG1E;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gCAAgC,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAwBzG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACrC,aAAa,EAAE,iBAAiB,EAChC,WAAW,EAAE,MAAM,GACpB,iBAAiB,CAanB;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CACzC,cAAc,EAAE,cAAc,GAAG,SAAS,EAC1C,iBAAiB,EAAE,MAAM,GAAG,SAAS,EACrC,mBAAmB,EAAE,MAAM,GAAG,IAAI,GACnC,cAAc,GAAG,SAAS,CAmC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,iBAAiB,EAAE,MAAM,GAAG,SAAS,EACrC,gBAAgB,EAAE,MAAM,EACxB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAC9B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqCxB"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UaAlignment - pure functions that align a fingerprint profile's version
|
|
3
|
+
* surfaces (User-Agent string, UA-CH brands/full-version list, the
|
|
4
|
+
* platform-consistency config, and injectable headers) with the version of
|
|
5
|
+
* the binary that is actually running.
|
|
6
|
+
*
|
|
7
|
+
* The fingerprint pool routinely ships profiles a few majors behind the
|
|
8
|
+
* shipped binary (132–135 vs 147+); an unaligned UA contradicts
|
|
9
|
+
* `Browser.getVersion` and every UA-CH surface - an instant detection signal.
|
|
10
|
+
* The injector probes the binary version over CDP and feeds it in here; all
|
|
11
|
+
* the rewriting itself is deterministic string/structure work, unit-testable
|
|
12
|
+
* without a browser.
|
|
13
|
+
*/
|
|
14
|
+
import { log } from 'crawlee';
|
|
15
|
+
import { alignBrandList, buildSecChUaHeader, canonicalBrandList } from './ua-ch-brands.js';
|
|
16
|
+
/**
|
|
17
|
+
* Re-stamp the Chrome version in a UA string to the running binary's major.
|
|
18
|
+
*
|
|
19
|
+
* Chrome UA Reduction (shipped Chrome 107+) freezes minor/build/patch to
|
|
20
|
+
* 0.0.0 in the User-Agent string - the full build version lives only in
|
|
21
|
+
* UA-CH uaFullVersion. We must use major.0.0.0 here or risk producing a
|
|
22
|
+
* non-existent version string like "Chrome/147.0.7727.56" which is trivially
|
|
23
|
+
* detectable.
|
|
24
|
+
*
|
|
25
|
+
* Direction matters: the UA is always pulled UP to the real binary, never the
|
|
26
|
+
* binary's identity pushed down to the profile's older major. A UA announcing a
|
|
27
|
+
* version the TLS/H2 handshake does not corroborate is itself a hard block -
|
|
28
|
+
* measured on `search.shopping.naver.com`, which refuses a Chrome/147 UA sent
|
|
29
|
+
* over a Chrome 142 handshake (issue #131). The binary is the ground truth
|
|
30
|
+
* every other surface aligns to.
|
|
31
|
+
*/
|
|
32
|
+
export function alignUserAgentWithBrowserVersion(userAgent, browserVersion) {
|
|
33
|
+
if (!browserVersion || !userAgent) {
|
|
34
|
+
return userAgent;
|
|
35
|
+
}
|
|
36
|
+
const uaMatch = userAgent.match(/Chrome\/(\d+\.\d+\.\d+\.\d+)/);
|
|
37
|
+
if (!uaMatch) {
|
|
38
|
+
return userAgent;
|
|
39
|
+
}
|
|
40
|
+
const majorVersion = browserVersion.split('.')[0];
|
|
41
|
+
const frozenVersion = `${majorVersion}.0.0.0`;
|
|
42
|
+
if (uaMatch[1] === frozenVersion) {
|
|
43
|
+
return userAgent;
|
|
44
|
+
}
|
|
45
|
+
const alignedUA = userAgent.replace(/Chrome\/\d+\.\d+\.\d+\.\d+/, `Chrome/${frozenVersion}`);
|
|
46
|
+
log.warning('User-Agent version mismatch detected. Aligning UA with running Chrome binary.', {
|
|
47
|
+
previousVersion: uaMatch[1],
|
|
48
|
+
binaryVersion: browserVersion,
|
|
49
|
+
alignedTo: frozenVersion,
|
|
50
|
+
});
|
|
51
|
+
return alignedUA;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Align UA-CH brands with the actual running Chrome binary version.
|
|
55
|
+
*
|
|
56
|
+
* Every entry is rewritten, GREASE included. The GREASE token is not bogus
|
|
57
|
+
* padding: Chromium derives its separators, its fake version and the order of
|
|
58
|
+
* the three-entry list from the major version (see `ua-ch-brands.ts`), so a
|
|
59
|
+
* profile's GREASE token is a fingerprint of the major that profile came from.
|
|
60
|
+
* Keeping a Chrome 134 GREASE on a Chrome 147 UA produced a `sec-ch-ua` no
|
|
61
|
+
* Chromium has ever emitted - and a hard, challenge-free HTTP 418 on
|
|
62
|
+
* `search.shopping.naver.com` (issue #131).
|
|
63
|
+
*/
|
|
64
|
+
export function alignUAClientHintsVersion(uaClientHints, fullVersion) {
|
|
65
|
+
const majorVersion = fullVersion.split('.')[0];
|
|
66
|
+
return {
|
|
67
|
+
...uaClientHints,
|
|
68
|
+
brands: uaClientHints.brands
|
|
69
|
+
? alignBrandList(uaClientHints.brands, majorVersion)
|
|
70
|
+
: uaClientHints.brands,
|
|
71
|
+
fullVersionList: uaClientHints.fullVersionList
|
|
72
|
+
? alignBrandList(uaClientHints.fullVersionList, fullVersion)
|
|
73
|
+
: uaClientHints.fullVersionList,
|
|
74
|
+
uaFullVersion: fullVersion,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Per-platform UA "body" (everything between "Mozilla/5.0 (" … the OS token …
|
|
79
|
+
* ") AppleWebKit/537.36 (KHTML, like Gecko) Chrome/<ver> Safari/537.36").
|
|
80
|
+
* Used to synthesize a version-aligned fallback UA on the
|
|
81
|
+
* useFingerprintDefaults path so we never bake in the static Chrome/134.0.0.0
|
|
82
|
+
* fallback from platform-consistency. Keys match the requestedPlatform values
|
|
83
|
+
* (navigator.platform strings).
|
|
84
|
+
*/
|
|
85
|
+
const PLATFORM_UA_OS_TOKEN = {
|
|
86
|
+
'Win32': 'Windows NT 10.0; Win64; x64',
|
|
87
|
+
'MacIntel': 'Macintosh; Intel Mac OS X 10_15_7',
|
|
88
|
+
'Linux x86_64': 'X11; Linux x86_64',
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Platform-consistency config alignment: when using real fingerprint data,
|
|
92
|
+
* align its UA/appVersion with the actual binary version; when using
|
|
93
|
+
* hardcoded defaults, inject a minimal version-aligned UA for any known
|
|
94
|
+
* platform (Win32 / MacIntel / Linux x86_64) so we don't bake in the static
|
|
95
|
+
* Chrome/134.0.0.0 fallback. Returns the input untouched when no platform is
|
|
96
|
+
* requested - so the UA-mismatch warn log doesn't fire for runs that never
|
|
97
|
+
* inject the platform-consistency override.
|
|
98
|
+
*/
|
|
99
|
+
export function alignPlatformConfigWithBinary(platformConfig, requestedPlatform, actualChromeVersion) {
|
|
100
|
+
if (!requestedPlatform) {
|
|
101
|
+
return platformConfig;
|
|
102
|
+
}
|
|
103
|
+
if (platformConfig?.userAgent && actualChromeVersion) {
|
|
104
|
+
return {
|
|
105
|
+
...platformConfig,
|
|
106
|
+
userAgent: alignUserAgentWithBrowserVersion(platformConfig.userAgent, actualChromeVersion),
|
|
107
|
+
appVersion: platformConfig.appVersion
|
|
108
|
+
? alignUserAgentWithBrowserVersion(platformConfig.appVersion, actualChromeVersion)
|
|
109
|
+
: platformConfig.appVersion,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const osToken = PLATFORM_UA_OS_TOKEN[requestedPlatform];
|
|
113
|
+
if (!platformConfig && actualChromeVersion && osToken) {
|
|
114
|
+
// useFingerprintDefaults=true path: override only the UA/appVersion
|
|
115
|
+
// fields so the hardcoded platform defaults pick up the real Chrome
|
|
116
|
+
// version instead of Chrome/134. appVersion is the UA minus the
|
|
117
|
+
// leading "Mozilla/".
|
|
118
|
+
//
|
|
119
|
+
// MAJOR.0.0.0, never the full build version: Chrome UA Reduction
|
|
120
|
+
// (107+) freezes minor/build/patch to zero in the UA string, so a
|
|
121
|
+
// synthesized "Chrome/147.0.7727.56" is a shape that no real Chrome
|
|
122
|
+
// emits - and it would contradict the plan-level `userAgent`
|
|
123
|
+
// (which alignUserAgentWithBrowserVersion already froze) plus every
|
|
124
|
+
// sec-ch-ua header derived from it. The full build version belongs
|
|
125
|
+
// only in UA-CH `uaFullVersion` / `fullVersionList`.
|
|
126
|
+
const frozenVersion = `${actualChromeVersion.split('.')[0]}.0.0.0`;
|
|
127
|
+
const userAgent = `Mozilla/5.0 (${osToken}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${frozenVersion} Safari/537.36`;
|
|
128
|
+
return {
|
|
129
|
+
userAgent,
|
|
130
|
+
appVersion: userAgent.replace(/^Mozilla\//, ''),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return platformConfig;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Filter fingerprint-generator headers down to the set injectable via CDP,
|
|
137
|
+
* apply the resolved Accept-Language (it wins over whatever the generator
|
|
138
|
+
* headers had so `fingerprintOptions.locale: 'ko-KR'` reaches the wire), and
|
|
139
|
+
* stamp the version-aligned User-Agent.
|
|
140
|
+
*
|
|
141
|
+
* `binaryVersion` also rewrites the UA-CH request headers, which
|
|
142
|
+
* `Network.setExtraHTTPHeaders` puts on the wire ABOVE whatever the
|
|
143
|
+
* `setUserAgentOverride` metadata would have produced. Forwarding the
|
|
144
|
+
* generator's copy verbatim shipped three separate contradictions (issue #131):
|
|
145
|
+
*
|
|
146
|
+
* - the profile's ORIGINAL major next to an aligned User-Agent;
|
|
147
|
+
* - a GREASE token from that original major;
|
|
148
|
+
* - a third-party brand - 44 of the 200 bundled non-Apify rows carry a
|
|
149
|
+
* `sec-ch-ua` header advertising **Brave** while their JS-side
|
|
150
|
+
* `userAgentData.brands` says Google Chrome. The brand-cohort gate only
|
|
151
|
+
* inspected the JS side, so the header walked straight past it.
|
|
152
|
+
*
|
|
153
|
+
* So `sec-ch-ua` is rebuilt from scratch - the canonical list a real Chrome of
|
|
154
|
+
* this binary emits - rather than aligned in place.
|
|
155
|
+
* `sec-ch-ua-full-version-list` is dropped instead of rewritten: it is a
|
|
156
|
+
* high-entropy hint that real Chrome sends only after an origin asks via
|
|
157
|
+
* `accept-ch`, so forcing it onto every request is itself a tell. Chrome emits
|
|
158
|
+
* it from the UA metadata when it is actually requested.
|
|
159
|
+
*
|
|
160
|
+
* Omit the argument (or pass null) to leave the headers alone.
|
|
161
|
+
*/
|
|
162
|
+
export function buildInjectableHeaders(headers, resolvedLanguages, alignedUserAgent, binaryVersion) {
|
|
163
|
+
const filteredHeaders = {};
|
|
164
|
+
const allowedHeaders = ['accept', 'accept-encoding', 'accept-language', 'user-agent', 'referer', 'sec-ch-ua', 'sec-ch-ua-mobile', 'sec-ch-ua-platform', 'sec-ch-ua-full-version-list'];
|
|
165
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
166
|
+
if (allowedHeaders.includes(key.toLowerCase()) && typeof value === 'string') {
|
|
167
|
+
filteredHeaders[key] = value;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (resolvedLanguages) {
|
|
171
|
+
filteredHeaders['accept-language'] = resolvedLanguages;
|
|
172
|
+
delete filteredHeaders['Accept-Language'];
|
|
173
|
+
}
|
|
174
|
+
if (alignedUserAgent) {
|
|
175
|
+
filteredHeaders['user-agent'] = alignedUserAgent;
|
|
176
|
+
delete filteredHeaders['User-Agent'];
|
|
177
|
+
}
|
|
178
|
+
if (binaryVersion) {
|
|
179
|
+
const majorVersion = binaryVersion.split('.')[0];
|
|
180
|
+
let hadSecChUa = false;
|
|
181
|
+
for (const key of Object.keys(filteredHeaders)) {
|
|
182
|
+
const name = key.toLowerCase();
|
|
183
|
+
if (name === 'sec-ch-ua') {
|
|
184
|
+
hadSecChUa = true;
|
|
185
|
+
delete filteredHeaders[key];
|
|
186
|
+
}
|
|
187
|
+
else if (name === 'sec-ch-ua-full-version-list') {
|
|
188
|
+
delete filteredHeaders[key];
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (hadSecChUa) {
|
|
192
|
+
filteredHeaders['sec-ch-ua'] = buildSecChUaHeader(canonicalBrandList(majorVersion));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return filteredHeaders;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=ua-alignment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ua-alignment.js","sourceRoot":"","sources":["../../src/fingerprinting/ua-alignment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAI9B,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE3F;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gCAAgC,CAAC,SAAiB,EAAE,cAA6B;IAC7F,IAAI,CAAC,cAAc,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAChE,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,MAAM,YAAY,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,aAAa,GAAG,GAAG,YAAY,QAAQ,CAAC;IAE9C,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,aAAa,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,MAAM,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,4BAA4B,EAAE,UAAU,aAAa,EAAE,CAAC,CAAC;IAC7F,GAAG,CAAC,OAAO,CAAC,+EAA+E,EAAE;QACzF,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC;QAC3B,aAAa,EAAE,cAAc;QAC7B,SAAS,EAAE,aAAa;KAC3B,CAAC,CAAC;IACH,OAAO,SAAS,CAAC;AACrB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,yBAAyB,CACrC,aAAgC,EAChC,WAAmB;IAEnB,MAAM,YAAY,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAE/C,OAAO;QACH,GAAG,aAAa;QAChB,MAAM,EAAE,aAAa,CAAC,MAAM;YACxB,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,MAAM,EAAE,YAAY,CAAC;YACpD,CAAC,CAAC,aAAa,CAAC,MAAM;QAC1B,eAAe,EAAE,aAAa,CAAC,eAAe;YAC1C,CAAC,CAAC,cAAc,CAAC,aAAa,CAAC,eAAe,EAAE,WAAW,CAAC;YAC5D,CAAC,CAAC,aAAa,CAAC,eAAe;QACnC,aAAa,EAAE,WAAW;KAC7B,CAAC;AACN,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,oBAAoB,GAA2B;IACjD,OAAO,EAAE,6BAA6B;IACtC,UAAU,EAAE,mCAAmC;IAC/C,cAAc,EAAE,mBAAmB;CACtC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,6BAA6B,CACzC,cAA0C,EAC1C,iBAAqC,EACrC,mBAAkC;IAElC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACrB,OAAO,cAAc,CAAC;IAC1B,CAAC;IACD,IAAI,cAAc,EAAE,SAAS,IAAI,mBAAmB,EAAE,CAAC;QACnD,OAAO;YACH,GAAG,cAAc;YACjB,SAAS,EAAE,gCAAgC,CAAC,cAAc,CAAC,SAAS,EAAE,mBAAmB,CAAC;YAC1F,UAAU,EAAE,cAAc,CAAC,UAAU;gBACjC,CAAC,CAAC,gCAAgC,CAAC,cAAc,CAAC,UAAU,EAAE,mBAAmB,CAAC;gBAClF,CAAC,CAAC,cAAc,CAAC,UAAU;SAClC,CAAC;IACN,CAAC;IACD,MAAM,OAAO,GAAG,oBAAoB,CAAC,iBAAiB,CAAC,CAAC;IACxD,IAAI,CAAC,cAAc,IAAI,mBAAmB,IAAI,OAAO,EAAE,CAAC;QACpD,oEAAoE;QACpE,oEAAoE;QACpE,gEAAgE;QAChE,sBAAsB;QACtB,EAAE;QACF,iEAAiE;QACjE,kEAAkE;QAClE,oEAAoE;QACpE,6DAA6D;QAC7D,oEAAoE;QACpE,mEAAmE;QACnE,qDAAqD;QACrD,MAAM,aAAa,GAAG,GAAG,mBAAmB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QACnE,MAAM,SAAS,GAAG,gBAAgB,OAAO,mDAAmD,aAAa,gBAAgB,CAAC;QAC1H,OAAO;YACH,SAAS;YACT,UAAU,EAAE,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;SAClD,CAAC;IACN,CAAC;IACD,OAAO,cAAc,CAAC;AAC1B,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,sBAAsB,CAClC,OAA+B,EAC/B,iBAAqC,EACrC,gBAAwB,EACxB,aAA6B;IAE7B,MAAM,eAAe,GAA2B,EAAE,CAAC;IACnD,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,6BAA6B,CAAC,CAAC;IACvL,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,IAAI,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC1E,eAAe,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACjC,CAAC;IACL,CAAC;IAED,IAAI,iBAAiB,EAAE,CAAC;QACpB,eAAe,CAAC,iBAAiB,CAAC,GAAG,iBAAiB,CAAC;QACvD,OAAO,eAAe,CAAC,iBAAiB,CAAC,CAAC;IAC9C,CAAC;IAED,IAAI,gBAAgB,EAAE,CAAC;QACnB,eAAe,CAAC,YAAY,CAAC,GAAG,gBAAgB,CAAC;QACjD,OAAO,eAAe,CAAC,YAAY,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAChB,MAAM,YAAY,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACjD,IAAI,UAAU,GAAG,KAAK,CAAC;QACvB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;YAC/B,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;gBACvB,UAAU,GAAG,IAAI,CAAC;gBAClB,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;YAChC,CAAC;iBAAM,IAAI,IAAI,KAAK,6BAA6B,EAAE,CAAC;gBAChD,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;YAChC,CAAC;QACL,CAAC;QACD,IAAI,UAAU,EAAE,CAAC;YACb,eAAe,CAAC,WAAW,CAAC,GAAG,kBAAkB,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC,CAAC;QACxF,CAAC;IACL,CAAC;IAED,OAAO,eAAe,CAAC;AAC3B,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UA-CH brand-list derivation - the GREASE token, its version, and the order
|
|
3
|
+
* of the three-entry brand list are all deterministic functions of the Chrome
|
|
4
|
+
* major version. This module is the single source of truth for that
|
|
5
|
+
* derivation; every surface that emits `sec-ch-ua` /
|
|
6
|
+
* `navigator.userAgentData.brands` (JS injection, CDP
|
|
7
|
+
* `Network.setUserAgentOverride` metadata, the native FingerprintConfig JSON,
|
|
8
|
+
* the bundled profile tables) must go through it.
|
|
9
|
+
*
|
|
10
|
+
* Why this matters: the GREASE entry is NOT arbitrary padding. Chromium
|
|
11
|
+
* (`components/embedder_support/user_agent_utils.cc`,
|
|
12
|
+
* `GetGreasedUserAgentBrandVersion` / `GenerateBrandVersionList`) derives the
|
|
13
|
+
* separators, the fake version and the list order from the major version:
|
|
14
|
+
*
|
|
15
|
+
* brand = 'Not' + chars[major % 11] + 'A' + chars[(major + 1) % 11] + 'Brand'
|
|
16
|
+
* version = versions[major % 3]
|
|
17
|
+
* order = ORDERS[major % 6] // permutation of [greasey, chromium, brand]
|
|
18
|
+
*
|
|
19
|
+
* So a profile's GREASE token is a fingerprint of the major it was harvested
|
|
20
|
+
* from. Carrying a Chrome 134 GREASE (`"Not:A-Brand";v="24"`) on a Chrome 147
|
|
21
|
+
* User-Agent yields a `sec-ch-ua` no Chromium has ever emitted - four lines of
|
|
22
|
+
* server-side code catch it. `search.shopping.naver.com` does exactly that and
|
|
23
|
+
* answers HTTP 418 with no challenge (issue #131).
|
|
24
|
+
*
|
|
25
|
+
* Corroboration for the derivation (real Chrome, on the wire): majors 116
|
|
26
|
+
* (`Not)A;Brand`/24), 128 (`Not;A=Brand`/24), 131 (`Not_A Brand`/24), 142
|
|
27
|
+
* (`Not_A Brand`/99, accepted by Naver). The order rule was verified against
|
|
28
|
+
* the 187 harvested `sec-ch-ua` strings bundled in `non-apify-profiles.json`
|
|
29
|
+
* (majors 140, 142, 143, 144, 145, 146 - every one matches `major % 6`).
|
|
30
|
+
*/
|
|
31
|
+
export interface BrandVersion {
|
|
32
|
+
brand: string;
|
|
33
|
+
version: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Match the UA-CH GREASE brand token. Chrome rotates the label across releases
|
|
37
|
+
* ("Not_A Brand", "Not)A;Brand", "Not.A/Brand", …); the separators vary but the
|
|
38
|
+
* Not?A?Brand shape is stable. Anchored, so it only ever matches the GREASE
|
|
39
|
+
* entry and never a real brand.
|
|
40
|
+
*/
|
|
41
|
+
export declare function isGreaseBrand(brand: string): boolean;
|
|
42
|
+
/** The GREASE brand + version a real Chromium of this major emits. */
|
|
43
|
+
export declare function greasedBrandForMajor(major: number): BrandVersion;
|
|
44
|
+
/**
|
|
45
|
+
* Rebuild a UA-CH brand list so it is byte-identical to what Chromium
|
|
46
|
+
* `version` emits: derived GREASE token, real brands re-stamped to `version`,
|
|
47
|
+
* and the triple permuted by `major % 6`.
|
|
48
|
+
*
|
|
49
|
+
* `version` selects the surface, from its own shape:
|
|
50
|
+
* - `"147"` → the `brands` surface; GREASE version is `"8"`
|
|
51
|
+
* - `"147.0.7727.56"` → the `fullVersionList` surface; GREASE version is `"8.0.0.0"`
|
|
52
|
+
*
|
|
53
|
+
* The profile's real brand *names* are preserved (a Chromium-only profile stays
|
|
54
|
+
* Chromium-only); only versions, the GREASE entry and the order are rewritten.
|
|
55
|
+
* A GREASE entry is added when the profile has none - a two-brand `sec-ch-ua`
|
|
56
|
+
* is refused by the same checks that reject a mismatched GREASE.
|
|
57
|
+
*/
|
|
58
|
+
export declare function alignBrandList(brands: BrandVersion[], version: string): BrandVersion[];
|
|
59
|
+
/**
|
|
60
|
+
* The canonical brand list of a real Google Chrome build of `version` - what
|
|
61
|
+
* `sec-ch-ua` looks like when we have no profile brands to preserve.
|
|
62
|
+
*/
|
|
63
|
+
export declare function canonicalBrandList(version: string): BrandVersion[];
|
|
64
|
+
/** Serialize a brand list into a `sec-ch-ua` / `sec-ch-ua-full-version-list` header value. */
|
|
65
|
+
export declare function buildSecChUaHeader(brands: BrandVersion[]): string;
|
|
66
|
+
/**
|
|
67
|
+
* Does this brand list carry the GREASE token its own major implies?
|
|
68
|
+
*
|
|
69
|
+
* Used as a pool-contamination gate: a real Chrome profile always agrees with
|
|
70
|
+
* the derivation, so a disagreement means the brand list was synthesized or
|
|
71
|
+
* re-stamped by something that did not know the rule (including older versions
|
|
72
|
+
* of this crawler). Returns a human-readable reason, or null when coherent.
|
|
73
|
+
*/
|
|
74
|
+
export declare function describeGreaseIncoherence(brands: BrandVersion[]): string | null;
|
|
75
|
+
/**
|
|
76
|
+
* JS source for an expression that derives the brand list *inside the page*.
|
|
77
|
+
*
|
|
78
|
+
* The injected-script fallbacks (ua-ch, datadome-bypass) learn the Chrome
|
|
79
|
+
* version only at runtime, by parsing `navigator.userAgent`, so they cannot use
|
|
80
|
+
* the helpers above at build time. This keeps their derivation identical to
|
|
81
|
+
* ours instead of hardcoding a literal GREASE token that rots.
|
|
82
|
+
*
|
|
83
|
+
* @param majorExpr in-scope JS expression holding the major version
|
|
84
|
+
* @param versionExpr in-scope JS expression holding the version to stamp on the real brands
|
|
85
|
+
* @param style 'major' for the `brands` surface, 'full' for `fullVersionList`
|
|
86
|
+
*/
|
|
87
|
+
export declare function brandListScriptExpression(majorExpr: string, versionExpr: string, style: 'major' | 'full'): string;
|
|
88
|
+
//# sourceMappingURL=ua-ch-brands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ua-ch-brands.d.ts","sourceRoot":"","sources":["../../src/fingerprinting/ua-ch-brands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACnB;AAsBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,sEAAsE;AACtE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAIhE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CA+BtF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,EAAE,CAKlE;AAED,8FAA8F;AAC9F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAEjE;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,GAAG,IAAI,CAoB/E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,yBAAyB,CACrC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,GAAG,MAAM,GACxB,MAAM,CAeR"}
|