Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions public/sw.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
49 changes: 39 additions & 10 deletions src/utils/captcha-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
];

/**
Expand All @@ -32,6 +43,7 @@ const HEAVY_COOKIE_DOMAINS = [
"facebook.com",
"instagram.com",
"twitter.com",
"x.com",
"linkedin.com",
"microsoft.com",
"apple.com",
Expand All @@ -40,7 +52,9 @@ const HEAVY_COOKIE_DOMAINS = [
"discord.com",
"github.com",
"reddit.com",
"twitch.tv"
"twitch.tv",
"tiktok.com",
"pinterest.com"
];

/**
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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";
Expand Down
10 changes: 3 additions & 7 deletions src/utils/iframe-interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
"; "
)
};

/**
Expand Down