diff --git a/browse/src/auto-cookie-persist.ts b/browse/src/auto-cookie-persist.ts index 0d2b631fc..6c7bfd290 100644 --- a/browse/src/auto-cookie-persist.ts +++ b/browse/src/auto-cookie-persist.ts @@ -133,6 +133,11 @@ function lockPath(config: BrowseConfig): string { return path.join(autoDir(config), `${computeProfileId(config)}.lock`); } +function normalizeCookieDomain(domain: string): string { + const d = domain.startsWith('.') ? domain.slice(1) : domain; + return d.toLowerCase(); +} + /** * Keep only cookies that are safe and sensible to persist: * - persistent (expires !== -1) and not already expired, @@ -150,9 +155,9 @@ export function filterPersistableCookies( if (!c || typeof c.name !== 'string' || typeof c.value !== 'string') return false; if (typeof c.domain !== 'string' || !c.domain) return false; // Session cookie — Playwright reports expires === -1. Never persist. - if (typeof c.expires !== 'number' || c.expires === -1) return false; + if (typeof c.expires !== 'number' || c.expires === -1 || !Number.isFinite(c.expires)) return false; if (c.expires <= nowSec) return false; // already expired - const d = c.domain.startsWith('.') ? c.domain.slice(1) : c.domain; + const d = normalizeCookieDomain(c.domain); if (d === 'localhost' || d.endsWith('.internal') || d === '169.254.169.254') return false; if (allowlist && !hostMatchesAllowlist(c.domain, allowlist)) return false; return true; diff --git a/browse/test/auto-cookie-persist.test.ts b/browse/test/auto-cookie-persist.test.ts index 0771c2623..a18af4684 100644 --- a/browse/test/auto-cookie-persist.test.ts +++ b/browse/test/auto-cookie-persist.test.ts @@ -100,13 +100,24 @@ describe('cookie filter', () => { test('rejects internal-network domains', () => { const kept = filterPersistableCookies([ cookie({ name: 'lh', domain: 'localhost' }), + cookie({ name: 'lh2', domain: 'LOCALHOST' }), cookie({ name: 'meta', domain: '169.254.169.254' }), cookie({ name: 'int', domain: 'foo.internal' }), + cookie({ name: 'int2', domain: 'Foo.INTERNAL' }), cookie({ name: 'ok', domain: 'example.com' }), ], null); expect(kept.map(c => c.name)).toEqual(['ok']); }); + test('rejects malformed expires values', () => { + const kept = filterPersistableCookies([ + cookie({ name: 'nan', expires: Number.NaN }), + cookie({ name: 'inf', expires: Number.POSITIVE_INFINITY }), + cookie({ name: 'ok' }), + ], null); + expect(kept.map(c => c.name)).toEqual(['ok']); + }); + test('applies host allowlist incl. leading-wildcard + apex', () => { const cookies = [ cookie({ name: 'a', domain: 'example.com' }),