diff --git a/public/sw.js b/public/sw.js index 3266d21..6e5ec15 100644 --- a/public/sw.js +++ b/public/sw.js @@ -20,16 +20,22 @@ const sj = new ScramjetServiceWorker({ // Enhanced CAPTCHA and Cloudflare verification support // List of CAPTCHA and verification domains that need special handling const CAPTCHA_DOMAINS = [ + // reCAPTCHA domains "google.com/recaptcha", "www.google.com/recaptcha", "recaptcha.net", "www.recaptcha.net", "gstatic.com/recaptcha", + // hCaptcha domains "hcaptcha.com", "newassets.hcaptcha.com", + "imgs.hcaptcha.com", + "js.hcaptcha.com", + // Cloudflare Turnstile and browser verification domains "challenges.cloudflare.com", "cloudflare.com/cdn-cgi/challenge", - "turnstile.cloudflare.com" + "turnstile.cloudflare.com", + "cf-chl-bypass.cloudflare.com" ]; // Domains that use heavy cookies and complex browser services @@ -42,17 +48,37 @@ const HEAVY_COOKIE_DOMAINS = [ "facebook.com", "instagram.com", "twitter.com", + "x.com", "linkedin.com", "microsoft.com", "apple.com", "netflix.com", - "spotify.com" + "spotify.com", + "discord.com", + "github.com", + "reddit.com", + "twitch.tv", + "tiktok.com", + "pinterest.com" +]; + +// URL patterns for CAPTCHA detection +const CAPTCHA_URL_PATTERNS = [ + "/recaptcha/", + "/hcaptcha/", + "/turnstile/", + "/cdn-cgi/challenge", + "cf-chl" ]; // Helper function to check if URL is CAPTCHA-related function isCaptchaRequest(url) { const urlStr = url.toString().toLowerCase(); - return CAPTCHA_DOMAINS.some((domain) => urlStr.includes(domain)); + // Check against known CAPTCHA domains + const matchesDomain = CAPTCHA_DOMAINS.some((domain) => urlStr.includes(domain)); + // Also check for common CAPTCHA patterns in URLs + const matchesPattern = CAPTCHA_URL_PATTERNS.some((pattern) => urlStr.includes(pattern)); + return matchesDomain || matchesPattern; } // Helper function to check if URL is from a site with heavy cookies diff --git a/src/utils/captcha-handler.ts b/src/utils/captcha-handler.ts index 7e0e18e..6583bb0 100644 --- a/src/utils/captcha-handler.ts +++ b/src/utils/captcha-handler.ts @@ -12,12 +12,23 @@ import { supportsStorageAccess, supportsHasStorageAccess } from "./storage-acces * List of CAPTCHA and verification-related domains */ const CAPTCHA_DOMAINS = [ - "google.com", + // reCAPTCHA domains + "google.com/recaptcha", + "www.google.com/recaptcha", "recaptcha.net", - "gstatic.com", + "www.recaptcha.net", + "gstatic.com/recaptcha", + // hCaptcha domains "hcaptcha.com", - "cloudflare.com", - "challenges.cloudflare.com" + "newassets.hcaptcha.com", + "imgs.hcaptcha.com", + "js.hcaptcha.com", + // Cloudflare Turnstile domains + "challenges.cloudflare.com", + "cloudflare.com/cdn-cgi/challenge", + "turnstile.cloudflare.com", + // Cloudflare browser verification + "cf-chl-bypass.cloudflare.com" ]; /** @@ -32,6 +43,7 @@ const HEAVY_COOKIE_DOMAINS = [ "facebook.com", "instagram.com", "twitter.com", + "x.com", "linkedin.com", "microsoft.com", "apple.com", @@ -40,7 +52,9 @@ const HEAVY_COOKIE_DOMAINS = [ "discord.com", "github.com", "reddit.com", - "twitch.tv" + "twitch.tv", + "tiktok.com", + "pinterest.com" ]; /** @@ -92,12 +106,19 @@ export function initializeCaptchaHandlers() { function configureCaptchaIframe(iframe: HTMLIFrameElement): void { const src = iframe.src || ""; - // Check if this is a CAPTCHA iframe + // Check if this is a CAPTCHA iframe using comprehensive pattern matching + // Use generic patterns that cover all variations const isCaptchaIframe = + // reCAPTCHA - covers recaptcha.net, google.com/recaptcha, gstatic.com/recaptcha src.includes("recaptcha") || + // hCaptcha - covers hcaptcha.com and all subdomains src.includes("hcaptcha") || + // Cloudflare Turnstile - covers turnstile.cloudflare.com + src.includes("turnstile") || + // Cloudflare browser verification patterns src.includes("challenges.cloudflare.com") || - src.includes("turnstile"); + src.includes("cf-chl") || + src.includes("cdn-cgi/challenge"); if (isCaptchaIframe) { // Ensure the iframe has proper sandbox permissions for CAPTCHA @@ -164,16 +185,24 @@ function enhanceCookieHandling() { set(value) { // Ensure SameSite=None for cookies in cross-origin contexts if (typeof value === "string") { - // Check if this is a CAPTCHA or heavy cookie site cookie + // Check if this is a CAPTCHA cookie (reCAPTCHA, hCaptcha, Cloudflare) const isCaptchaCookie = value.includes("_GRECAPTCHA") || + value.includes("grecaptcha") || value.includes("h-captcha") || - value.includes("cf_"); + value.includes("hcaptcha") || + value.includes("cf_") || + value.includes("cf_clearance") || + value.includes("__cf") || + value.includes("_cfuvid") || + value.includes("cf_chl"); const isImportantCookie = isCaptchaCookie || value.includes("session") || value.includes("auth") || - value.includes("token"); + value.includes("token") || + value.includes("csrf") || + value.includes("xsrf"); if (isImportantCookie && !value.includes("SameSite")) { value += "; SameSite=None; Secure"; diff --git a/src/utils/iframe-interceptor.ts b/src/utils/iframe-interceptor.ts index 098156c..0fc4c1b 100644 --- a/src/utils/iframe-interceptor.ts +++ b/src/utils/iframe-interceptor.ts @@ -29,13 +29,9 @@ export const IFRAME_CONFIG = { "allow-storage-access-by-user-activation" ].join(" "), // Essential feature policy for the iframe (reduced permissions for security) - allow: [ - "autoplay", - "clipboard-write", - "encrypted-media", - "fullscreen", - "storage-access" - ].join("; ") + allow: ["autoplay", "clipboard-write", "encrypted-media", "fullscreen", "storage-access"].join( + "; " + ) }; /**