From 1ed88c3aeb1c24256af011374e96ef05ad23cd74 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 11:45:32 +0000 Subject: [PATCH 1/3] Initial plan From 422a90d9817027c16c0ee287fbb98863e3ee992c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 11:50:08 +0000 Subject: [PATCH 2/3] Fix CAPTCHA and Cloudflare verification cookie and request handling Co-authored-by: sriail <225764385+sriail@users.noreply.github.com> --- public/sw.js | 15 ++++++-- src/utils/captcha-handler.ts | 73 ++++++++++++++++++++++++++---------- 2 files changed, 66 insertions(+), 22 deletions(-) diff --git a/public/sw.js b/public/sw.js index efad95a..aecdb4b 100644 --- a/public/sw.js +++ b/public/sw.js @@ -18,7 +18,9 @@ const CAPTCHA_DOMAINS = [ "newassets.hcaptcha.com", "challenges.cloudflare.com", "cloudflare.com/cdn-cgi/challenge", - "turnstile.cloudflare.com" + "turnstile.cloudflare.com", + "cdn-cgi", + "cf-assets" ]; // Helper function to check if URL is CAPTCHA-related @@ -37,11 +39,18 @@ function enhanceCaptchaRequest(request) { headers.set("Accept", "*/*"); } - // Preserve credentials for CAPTCHA cookies + // Ensure critical headers are preserved + if (request.referrer && !headers.has("Referer")) { + headers.set("Referer", request.referrer); + } + + // Preserve credentials for CAPTCHA cookies - don't change mode as it can break cookies return new Request(request, { headers: headers, credentials: "include", - mode: request.mode === "navigate" ? "same-origin" : request.mode + mode: request.mode, + cache: request.cache, + redirect: request.redirect }); } diff --git a/src/utils/captcha-handler.ts b/src/utils/captcha-handler.ts index 47a74e5..968690d 100644 --- a/src/utils/captcha-handler.ts +++ b/src/utils/captcha-handler.ts @@ -13,7 +13,10 @@ const CAPTCHA_DOMAINS = [ "gstatic.com", "hcaptcha.com", "cloudflare.com", - "challenges.cloudflare.com" + "challenges.cloudflare.com", + "cdn-cgi", + "cf-assets", + "turnstile" ]; /** @@ -78,22 +81,33 @@ function enhanceCookieHandling() { // Store original cookie descriptor const originalCookieDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, "cookie"); - if (originalCookieDescriptor) { - Object.defineProperty(document, "cookie", { - get() { - return originalCookieDescriptor.get?.call(this) || ""; - }, - set(value) { - // Ensure SameSite=None for CAPTCHA cookies in cross-origin iframes - if (typeof value === "string" && value.includes("_GRECAPTCHA")) { - if (!value.includes("SameSite")) { - value += "; SameSite=None; Secure"; + if (originalCookieDescriptor && originalCookieDescriptor.configurable) { + try { + Object.defineProperty(document, "cookie", { + get() { + return originalCookieDescriptor.get?.call(this) || ""; + }, + set(value) { + // Ensure SameSite=None for CAPTCHA cookies in cross-origin iframes + if (typeof value === "string") { + // Handle various CAPTCHA-related cookies + const isCaptchaCookie = value.includes("_GRECAPTCHA") || + value.includes("_hcaptcha") || + value.includes("cf_clearance") || + value.includes("__cf_bm"); + + if (isCaptchaCookie && !value.includes("SameSite")) { + // Add SameSite=None and Secure for cross-origin cookies + value += "; SameSite=None; Secure"; + } } - } - originalCookieDescriptor.set?.call(this, value); - }, - configurable: true - }); + originalCookieDescriptor.set?.call(this, value); + }, + configurable: true + }); + } catch (error) { + console.warn("Failed to enhance cookie handling:", error); + } } } @@ -119,7 +133,7 @@ function enhanceNetworkRequests() { if (isCaptchaRequest) { // Ensure credentials are included init = init || {}; - if (!init.credentials) { + if (!init.credentials || init.credentials === "omit") { init.credentials = "include"; } @@ -128,6 +142,11 @@ function enhanceNetworkRequests() { if (!init.headers.has("Accept")) { init.headers.set("Accept", "*/*"); } + + // Don't override cache mode for CAPTCHA requests + if (!init.cache) { + init.cache = "default"; + } } return originalFetch.call(this, input, init); @@ -142,7 +161,9 @@ function enhanceNetworkRequests() { // Store original open method const originalOpen = xhr.open; - xhr.open = function (method: string, url: string | URL, ...args: any[]) { + const originalSend = xhr.send; + + xhr.open = function (method: string, url: string | URL, async?: boolean, username?: string | null, password?: string | null) { const urlStr = url.toString(); const isCaptchaRequest = CAPTCHA_DOMAINS.some((domain) => urlStr.includes(domain)); @@ -151,7 +172,21 @@ function enhanceNetworkRequests() { xhr.withCredentials = true; } - return originalOpen.call(this, method, url, ...args); + if (async !== undefined) { + if (username !== undefined) { + if (password !== undefined) { + return originalOpen.call(this, method, url, async, username, password); + } + return originalOpen.call(this, method, url, async, username); + } + return originalOpen.call(this, method, url, async); + } + return originalOpen.call(this, method, url); + }; + + // Ensure headers are properly set + xhr.send = function (body?: Document | XMLHttpRequestBodyInit | null) { + return originalSend.call(this, body); }; return xhr; From 0b1f50f6bc7862e73e5284159f9c7f8a86b011ae Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 20 Nov 2025 11:52:03 +0000 Subject: [PATCH 3/3] Enhance service worker to properly handle CAPTCHA requests through proxies Co-authored-by: sriail <225764385+sriail@users.noreply.github.com> --- public/sw.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/public/sw.js b/public/sw.js index aecdb4b..4981f00 100644 --- a/public/sw.js +++ b/public/sw.js @@ -66,11 +66,24 @@ self.addEventListener("fetch", function (event) { let request = event.request; if (isCaptcha) { request = enhanceCaptchaRequest(event.request); + console.debug("[CAPTCHA] Enhanced request for:", url); } if (url.startsWith(location.origin + __uv$config.prefix)) { + // For proxied CAPTCHA requests through UV, create a modified event + if (isCaptcha) { + const modifiedEvent = Object.create(event); + modifiedEvent.request = request; + return await uv.fetch(modifiedEvent); + } return await uv.fetch(event); } else if (sj.route(event)) { + // For proxied CAPTCHA requests through Scramjet, create a modified event + if (isCaptcha) { + const modifiedEvent = Object.create(event); + modifiedEvent.request = request; + return await sj.fetch(modifiedEvent); + } return await sj.fetch(event); } else { return await fetch(request);