fix(providers): claude-web 403 fix, no-auth providers misplaced in web-cookie - #3090
Conversation
…-cookie - Fix claude-web 403: use normalizeClaudeSessionCookieWithAutoRefresh() instead of sync normalizeClaudeSessionCookie() in execute() — the sync version never injects cf_clearance, causing all requests to 403 - Remove dead claude-web-auto-refresh.ts executor (only claude-web-with-auto-refresh.ts is wired in index.ts) - Clean up unused imports in claude-web.ts (createAutoRefreshMiddleware, refreshCookie, getCacheStatus, ClaudeWebCredentials interface) - Move duckduckgo-web from WEB_COOKIE_PROVIDERS to NOAUTH_PROVIDERS (anonymous, noAuth:true, per-request VQD token flow) - Move veoaifree-web from WEB_COOKIE_PROVIDERS to NOAUTH_PROVIDERS (authHint: "No auth required", 6 req/hr rate limit) - Add duckduckgo-web to providerAllowsOptionalApiKey - Remove both entries from webSessionCredentials.ts (kind:"none")
There was a problem hiding this comment.
Code Review
This pull request refactors the Claude Web executor by removing the ClaudeWebAutoRefreshExecutor wrapper and instead integrating cf_clearance injection directly into ClaudeWebExecutor via normalizeClaudeSessionCookieWithAutoRefresh. Additionally, it transitions the duckduckgo-web and veoaifree-web providers to the no-authentication provider list. The review feedback points out a critical issue: removing the auto-refresh wrapper completely eliminates the retry mechanism for expired or invalid cf_clearance tokens, and provides a code suggestion to restore this retry logic directly inside ClaudeWebExecutor.execute.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const message = error instanceof Error ? error.message : String(error); | ||
| // Continue anyway - request might fail, but that's OK | ||
| options?.log?.warn?.("CLAUDE-WEB", `cf_clearance injection failed: ${message}`); | ||
| // Continue anyway - the retry wrapper will handle 403 |
There was a problem hiding this comment.
Missing Retry and Auto-Refresh Logic for cf_clearance\n\nWith the removal of ClaudeWebAutoRefreshExecutor (the retry wrapper) in this PR, the automatic retry and refresh mechanism for Cloudflare Turnstile (cf_clearance) is completely lost.\n\nCurrently, normalizeClaudeSessionCookieWithAutoRefresh only attempts to solve Turnstile if cf_clearance is missing from the cookie. If the cookie already contains an expired or invalid cf_clearance token, it will skip auto-solving and proceed with the request, which will fail with a 403 or 401 error. Since there is no longer any retry wrapper, the request will fail permanently.\n\nTo restore this critical functionality, we should implement the retry logic directly inside ClaudeWebExecutor.execute in claude-web.ts.\n\nHere is how you can update execute to handle this:\n\ntypescript\n // Change const to let\n let fetchResponse = await tlsFetchClaude(completionUrl, {\n method: \"POST\",\n headers: {\n ...headers,\n Cookie: cookieHeader,\n },\n body: JSON.stringify(claudePayload),\n timeoutMs: FETCH_TIMEOUT_MS,\n stream: true,\n signal: combinedSignal,\n });\n\n // Retry once with a fresh cf_clearance token if we hit a 403 or 401\n if (fetchResponse.status === 403 || fetchResponse.status === 401) {\n log?.warn?.(\"CLAUDE-WEB\", `HTTP ${fetchResponse.status} - attempting to refresh cf_clearance and retry`);\n try {\n const freshCfClearance = await getCfClearanceToken({ force: true });\n const updatedCookieHeader = cookieHeader.includes(\"cf_clearance=\")\n ? cookieHeader.replace(/cf_clearance=[^;]+/, `cf_clearance=${freshCfClearance}`)\n : cookieHeader ? `${cookieHeader}; cf_clearance=${freshCfClearance}` : `cf_clearance=${freshCfClearance}`;\n\n log?.info?.(\"CLAUDE-WEB\", \"cf_clearance refreshed, retrying request\");\n fetchResponse = await tlsFetchClaude(completionUrl, {\n method: \"POST\",\n headers: {\n ...headers,\n Cookie: updatedCookieHeader,\n },\n body: JSON.stringify(claudePayload),\n timeoutMs: FETCH_TIMEOUT_MS,\n stream: true,\n signal: combinedSignal,\n });\n } catch (retryError) {\n const message = retryError instanceof Error ? retryError.message : String(retryError);\n log?.error?.(\"CLAUDE-WEB\", `Failed to auto-refresh cf_clearance on retry: ${message}`);\n }\n }\n
- claude-web: keep allowAutoSolve:true (correct cf_clearance injection) - providers.ts: keep duckduckgo-web removed from WEB_COOKIE_PROVIDERS (moved to NOAUTH_PROVIDERS in this branch)
|
Thank you @oyi77 for this fix! 🙏 The claude-web 403 root cause fix (async with ) and the NOAUTH provider reclassification for duckduckgo-web and veoaifree-web are exactly right. Resolved a minor conflict with the release branch (your version kept), then merged into release/v3.8.9. This will ship in the upcoming v3.8.9 release. |
…reclassification veoaifree-web was moved from WEB_COOKIE_PROVIDERS to NOAUTH_PROVIDERS in PR #3090 — it no longer appears in WEB_SESSION_CREDENTIAL_REQUIREMENTS.
…-cookie (diegosouzapw#3090) Integrated into release/v3.8.9 — resolved conflicts with release branch (allowAutoSolve:true preserved, duckduckgo-web correctly kept in NOAUTH_PROVIDERS).
…reclassification veoaifree-web was moved from WEB_COOKIE_PROVIDERS to NOAUTH_PROVIDERS in PR diegosouzapw#3090 — it no longer appears in WEB_SESSION_CREDENTIAL_REQUIREMENTS.
…-cookie (diegosouzapw#3090) Integrated into release/v3.8.9 — resolved conflicts with release branch (allowAutoSolve:true preserved, duckduckgo-web correctly kept in NOAUTH_PROVIDERS).
…reclassification veoaifree-web was moved from WEB_COOKIE_PROVIDERS to NOAUTH_PROVIDERS in PR diegosouzapw#3090 — it no longer appears in WEB_SESSION_CREDENTIAL_REQUIREMENTS.
…-cookie (diegosouzapw#3090) Integrated into release/v3.8.9 — resolved conflicts with release branch (allowAutoSolve:true preserved, duckduckgo-web correctly kept in NOAUTH_PROVIDERS).
…reclassification veoaifree-web was moved from WEB_COOKIE_PROVIDERS to NOAUTH_PROVIDERS in PR diegosouzapw#3090 — it no longer appears in WEB_SESSION_CREDENTIAL_REQUIREMENTS.
Summary
execute()method inclaude-web.tscalled the synchronousnormalizeClaudeSessionCookie()which never injectscf_clearance. Changed to asyncnormalizeClaudeSessionCookieWithAutoRefresh()which solves Cloudflare Turnstile and injects the token before the first request. This is the root cause of persistent 403 errors on v3.8.8.claude-web-auto-refresh.tswas never wired inindex.ts— onlyclaude-web-with-auto-refresh.tsis used. Removed dead code.claude-web.ts:createAutoRefreshMiddleware,refreshCookie,getCacheStatus,ClaudeWebCredentialsinterface, unusedstreamparam.duckduckgo-webto NOAUTH_PROVIDERS: Anonymous provider (noAuth:true, per-request VQD token) was incorrectly categorized as WEB_COOKIE.veoaifree-webto NOAUTH_PROVIDERS: AuthHint literally says "No auth required" — was incorrectly in WEB_COOKIE_PROVIDERS.duckduckgo-webtoproviderAllowsOptionalApiKey.webSessionCredentials.ts(both hadkind: "none"— not cookie-based).Test Plan
tests/unit/claude-web.test.ts— 13/13tests/unit/claude-web-auto-refresh.test.ts— 10 pass (6 skipped — need Playwright)tests/unit/duckduckgo-web-executor.test.ts— 14/14