fix(stealth): split minimal/full mode to eliminate detection lies on real Chrome

- CdpAttach mode: only removes navigator.webdriver (user's real Chrome
  already has genuine fingerprint, heavy patches create detectable lies)
- FullLaunch mode: applies all 32 patches (new Chrome needs full coverage)
- Improved webdriver removal: uses Object.defineProperty to override CDP
  getter on Navigator.prototype, not just delete
- CreepJS results: 0% stealth (was 20%), hasIframeProxy: gone

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
leeguooooo
2026-05-08 23:48:50 +09:00
co-authored by Claude Opus 4.6
parent 7ee3d5fb94
commit 81cdd3b216
2 changed files with 84 additions and 34 deletions
+14 -1
View File
@@ -1729,6 +1729,8 @@ fn chrome_relaunch_hint() -> &'static str {
}
/// Called after every successful launch / CDP connect / auto-connect.
/// Uses `CdpAttach` mode for external connections (minimal patches) and
/// `FullLaunch` mode for newly launched Chrome (all patches).
async fn apply_stealth_to_browser(state: &DaemonState) {
if env::var("AGENT_BROWSER_STEALTH").map(|v| v == "0").unwrap_or(false) {
return; // Explicitly disabled
@@ -1739,10 +1741,21 @@ async fn apply_stealth_to_browser(state: &DaemonState) {
let Ok(session_id) = mgr.active_session_id() else {
return;
};
// Determine mode: if we attached to an external browser, use minimal patches.
// The user's real Chrome already has a genuine fingerprint — heavy patches
// would create detectable "lies" (e.g. creepjs hasIframeProxy).
let mode = if mgr.is_cdp_connection() {
stealth::StealthMode::CdpAttach
} else {
stealth::StealthMode::FullLaunch
};
let locale = env::var("AGENT_BROWSER_LOCALE").ok();
if let Err(e) = stealth::apply_stealth(
&mgr.client,
session_id,
mode,
locale.as_deref(),
)
.await
@@ -1751,7 +1764,7 @@ async fn apply_stealth_to_browser(state: &DaemonState) {
}
// Also inject into the current page (already loaded before our init script)
if let Err(e) =
stealth::apply_stealth_to_current_page(&mgr.client, session_id, locale.as_deref()).await
stealth::apply_stealth_to_current_page(&mgr.client, session_id, mode, locale.as_deref()).await
{
eprintln!("[stealth] Failed to patch current page: {}", e);
}