fix(desktop): isolate AI account auth probes
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user