Skip to content

fix(providers): claude-web 403 fix, no-auth providers misplaced in web-cookie - #3090

Merged
diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.9from
oyi77:fix/web-cookie-providers-audit-v3.8.8-take2
Jun 3, 2026
Merged

diegosouzapw merged 2 commits into
diegosouzapw:release/v3.8.9from
oyi77:fix/web-cookie-providers-audit-v3.8.8-take2

Conversation

@oyi77

@oyi77 oyi77 commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fix claude-web 403: The execute() method in claude-web.ts called the synchronous normalizeClaudeSessionCookie() which never injects cf_clearance. Changed to async normalizeClaudeSessionCookieWithAutoRefresh() 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.
  • Remove dead executor: claude-web-auto-refresh.ts was never wired in index.ts — only claude-web-with-auto-refresh.ts is used. Removed dead code.
  • Clean up unused imports in claude-web.ts: createAutoRefreshMiddleware, refreshCookie, getCacheStatus, ClaudeWebCredentials interface, unused stream param.
  • Move duckduckgo-web to NOAUTH_PROVIDERS: Anonymous provider (noAuth:true, per-request VQD token) was incorrectly categorized as WEB_COOKIE.
  • Move veoaifree-web to NOAUTH_PROVIDERS: AuthHint literally says "No auth required" — was incorrectly in WEB_COOKIE_PROVIDERS.
  • Add duckduckgo-web to providerAllowsOptionalApiKey.
  • Remove both entries from webSessionCredentials.ts (both had kind: "none" — not cookie-based).

Test Plan

  • TypeScript typecheck passes (0 new errors)
  • ESLint passes (0 errors)
  • Unit tests: 34/34 pass (claude-web, duckduckgo-web, auto-refresh)
    • tests/unit/claude-web.test.ts — 13/13
    • tests/unit/claude-web-auto-refresh.test.ts — 10 pass (6 skipped — need Playwright)
    • tests/unit/duckduckgo-web-executor.test.ts — 14/14
  • Production build succeeds
  • Live testing: duckduckgo-web no-auth endpoint (requires server warm-up)
  • Live testing: claude-web with session cookie + cf_clearance injection

…-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")
@oyi77
oyi77 requested a review from diegosouzapw as a code owner June 3, 2026 08:57

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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

@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.8 to release/v3.8.9 June 3, 2026 09:34
- 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)
@diegosouzapw
diegosouzapw merged commit 9141e98 into diegosouzapw:release/v3.8.9 Jun 3, 2026
2 checks passed
@diegosouzapw

Copy link
Copy Markdown
Owner

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.

diegosouzapw added a commit that referenced this pull request Jun 3, 2026
…reclassification

veoaifree-web was moved from WEB_COOKIE_PROVIDERS to NOAUTH_PROVIDERS
in PR #3090 — it no longer appears in WEB_SESSION_CREDENTIAL_REQUIREMENTS.
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…-cookie (diegosouzapw#3090)

Integrated into release/v3.8.9 — resolved conflicts with release branch (allowAutoSolve:true preserved, duckduckgo-web correctly kept in NOAUTH_PROVIDERS).
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
…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.
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
…-cookie (diegosouzapw#3090)

Integrated into release/v3.8.9 — resolved conflicts with release branch (allowAutoSolve:true preserved, duckduckgo-web correctly kept in NOAUTH_PROVIDERS).
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
…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.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…-cookie (diegosouzapw#3090)

Integrated into release/v3.8.9 — resolved conflicts with release branch (allowAutoSolve:true preserved, duckduckgo-web correctly kept in NOAUTH_PROVIDERS).
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants