fix(desktop): isolate AI account auth probes

This commit is contained in:
2026-05-06 18:20:10 +08:00
parent a99d7a4971
commit f3487bcacf
11 changed files with 1713 additions and 270 deletions
+74 -46
View File
@@ -6,29 +6,6 @@ function normalizeText(value: unknown): string | null {
return trimmed ? trimmed : null
}
function hashText(value: string): string {
let hash = 0
for (let index = 0; index < value.length; index += 1) {
hash = ((hash << 5) - hash + value.charCodeAt(index)) | 0
}
return Math.abs(hash).toString(16).padStart(8, '0')
}
function boundedIdentity(prefix: string, raw: string): string {
const normalizedPrefix = prefix.trim().replace(/:+$/, '')
const normalizedRaw = raw.trim()
if (!normalizedRaw) {
return `${normalizedPrefix}:${hashText(prefix)}`
}
const candidate = `${normalizedPrefix}:${normalizedRaw}`
if (candidate.length <= 120) {
return candidate
}
return `${normalizedPrefix}:${hashText(normalizedRaw)}`
}
function normalizeURLPath(pathname: string): string {
const normalized = pathname.replace(/\/+$/, '')
return normalized === '/' ? '' : normalized
@@ -58,6 +35,79 @@ export interface GenericAIPageState {
challengeSignalCount: number
}
export function isLikelyGenericAICredentialName(name: string): boolean {
const normalized = name.trim().toLowerCase()
if (!normalized) {
return false
}
if (/(?:^|[-_.])(?:x[-_]?csrf|xsrf|csrf)(?:[-_]?token)?(?:$|[-_.])/.test(normalized)) {
return false
}
if (
/(?:^|[-_.])(?:slardar|analytics|monitor|telemetry|trace|tracing|log|logger|sentry|rum|perf|performance|abtest|experiment|visitor|guest|anonymous|device|webid|web_id|ttwid|hook|mstoken|ms_token|odin_tt|s_v_web_id|__ac_nonce|__ac_signature)(?:$|[-_.])/i.test(
normalized,
)
) {
return false
}
return /(token|session|auth|login|passport|ticket|jwt|refresh|access|sso)/i.test(normalized)
}
export function isLikelyGenericAICredentialValue(value: string | null | undefined): boolean {
const normalized = normalizeText(value)
if (!normalized) {
return false
}
if (/^(true|false|null|undefined|0|1)$/i.test(normalized)) {
return false
}
return normalized.length >= 8
}
export function genericAIHasVisibleAccountSignal(pageState: GenericAIPageState | null): boolean {
return (
Boolean(pageState?.displayName || pageState?.avatarUrl) ||
(pageState?.strongAuthSignalCount ?? 0) >= 2
)
}
export function genericAIPlatformRequiresVisibleCredentialSignal(platformId: string): boolean {
const normalizedPlatformId = platformId.trim().toLowerCase()
return normalizedPlatformId === 'qwen'
}
export function isLikelyPlatformAICredentialCookie(
platformId: string,
name: string,
value: string | null | undefined,
pageState?: GenericAIPageState | null,
): boolean {
const normalizedPlatformId = platformId.trim().toLowerCase()
const hasVisibleAccountSignal = genericAIHasVisibleAccountSignal(pageState ?? null)
if (normalizedPlatformId === 'doubao' || normalizedPlatformId === 'kimi') {
return false
}
if (!isLikelyGenericAICredentialName(name) || !isLikelyGenericAICredentialValue(value)) {
return false
}
if (
genericAIPlatformRequiresVisibleCredentialSignal(platformId) &&
!hasVisibleAccountSignal
) {
return false
}
return true
}
export function genericAIPageLooksAuthenticated(
currentURL: string,
pageState: GenericAIPageState | null,
@@ -92,27 +142,5 @@ export function genericAIPageLooksAuthenticated(
return (strongAuthSignalCount >= 2 || hasCredentialFingerprint) && !onConversationPath
}
return strongAuthSignalCount > 0 || onConversationPath || hasCredentialFingerprint
}
export function buildGenericAIPageFingerprintFallback(
platformId: string,
pageState?: GenericAIPageState | null,
): string | null {
const credentialFingerprint = normalizeText(pageState?.credentialFingerprint)
if (credentialFingerprint) {
return boundedIdentity(`${platformId}-session`, credentialFingerprint)
}
const fallbackFingerprint = normalizeText(pageState?.fingerprint)
if (!fallbackFingerprint) {
return null
}
const strongAuthSignalCount = pageState?.strongAuthSignalCount ?? 0
if (strongAuthSignalCount <= 0) {
return null
}
return boundedIdentity(`${platformId}-page`, fallbackFingerprint)
return strongAuthSignalCount > 0 || hasCredentialFingerprint
}