feat(cloudflare): cf-status preflight — skip re-solving when cf_clearance is still valid
Passing a Cloudflare challenge mints an HttpOnly cf_clearance cookie bound to IP+UA. 'chrome-use cf-status' (aliases cf/cloudflare-status/clearance) reports whether the active page is currently a CF challenge and whether a still-valid cf_clearance exists (read via CDP — HttpOnly is invisible to document.cookie), plus CF_VERIFIED_DEVICE trust, and a recommendation: proceed (already cleared, don't re-solve) / solve (challenge up, no clearance) / reissue (clearance present but page still blocks → IP/UA drifted). Lets an agent avoid re-solving what it already cleared — the persistence optimization. Pure helpers unit-tested; live -verified on a real cf_clearance.
This commit is contained in:
@@ -224,6 +224,40 @@ pub fn print_response_with_opts(resp: &Response, action: Option<&str>, opts: &Ou
|
||||
return;
|
||||
}
|
||||
|
||||
// Cloudflare challenge/clearance preflight (`cf-status`). Checked early
|
||||
// because its response carries `url`/`title`, which later generic
|
||||
// renderers would otherwise swallow.
|
||||
if action == Some("cf_status") {
|
||||
let challenged = data.get("challenged").and_then(|v| v.as_bool()).unwrap_or(false);
|
||||
let rec = data.get("recommendation").and_then(|v| v.as_str()).unwrap_or("?");
|
||||
let cl = data.get("clearance");
|
||||
let present = cl.and_then(|c| c.get("present")).and_then(|v| v.as_bool()).unwrap_or(false);
|
||||
let expired = cl.and_then(|c| c.get("expired")).and_then(|v| v.as_bool()).unwrap_or(false);
|
||||
let expires_in = cl.and_then(|c| c.get("expiresIn")).and_then(|v| v.as_i64());
|
||||
let device = data.get("deviceVerified").and_then(|v| v.as_bool()).unwrap_or(false);
|
||||
|
||||
let (icon, headline) = match rec {
|
||||
"proceed" => (color::success_indicator().to_string(), "cleared — no challenge, proceed"),
|
||||
"solve" => (color::warning_indicator().to_string(), "Cloudflare challenge active, no valid clearance — solve it"),
|
||||
"reissue" => (color::warning_indicator().to_string(), "challenge active but a clearance cookie exists — stale (IP/UA changed?), re-solve"),
|
||||
_ => (color::cyan("•").to_string(), "unknown"),
|
||||
};
|
||||
println!("{} {}", icon, headline);
|
||||
println!(" challenged: {}", if challenged { "yes" } else { "no" });
|
||||
let cl_desc = if !present {
|
||||
"absent".to_string()
|
||||
} else if expired {
|
||||
"present but EXPIRED".to_string()
|
||||
} else if let Some(s) = expires_in {
|
||||
format!("valid, expires in {}m {}s", s / 60, s % 60)
|
||||
} else {
|
||||
"present (session)".to_string()
|
||||
};
|
||||
println!(" cf_clearance: {}", cl_desc);
|
||||
println!(" device trusted: {}", if device { "yes (CF_VERIFIED_DEVICE)" } else { "no" });
|
||||
return;
|
||||
}
|
||||
|
||||
// Dialog status response
|
||||
if action == Some("dialog") {
|
||||
if let Some(has_dialog) = data.get("hasDialog").and_then(|v| v.as_bool()) {
|
||||
@@ -3195,6 +3229,10 @@ Get Info: chrome-use get <what> [selector]
|
||||
Check State: chrome-use is <what> <selector>
|
||||
visible, enabled, checked
|
||||
|
||||
Anti-bot: chrome-use stealth | cf-status
|
||||
stealth stealth self-check (webdriver/UA/plugins + overrides)
|
||||
cf-status Cloudflare challenge + cf_clearance preflight (skip re-solving)
|
||||
|
||||
Find Elements: chrome-use find <locator> <value> <action> [text]
|
||||
role, text, label, placeholder, alt, title, testid, first, last, nth
|
||||
|
||||
|
||||
Reference in New Issue
Block a user