fix: validate browser cookie replay partitions (#3672)
This commit is contained in:
parent
d3a9c5a2b8
commit
369f77a69f
|
|
@ -243,4 +243,37 @@ describe('BrowserSessionRegistry persistence', () => {
|
|||
expect(written.pendingCookieImports).toEqual({ [importedPartition]: '/staged/imported' })
|
||||
expect(written.pendingCookieDbPath).toBeNull()
|
||||
})
|
||||
|
||||
it('ignores pending cookie imports for invalid persisted profile partitions', async () => {
|
||||
const invalidPartition = 'persist:../../outside'
|
||||
const fsState = createFsState()
|
||||
seedMeta(fsState, {
|
||||
defaultSource: null,
|
||||
userAgent: null,
|
||||
userAgentByPartition: {},
|
||||
pendingCookieDbPath: null,
|
||||
pendingCookieImports: {
|
||||
[invalidPartition]: '/staged/evil'
|
||||
},
|
||||
profiles: [
|
||||
{
|
||||
id: 'profile-1',
|
||||
scope: 'imported',
|
||||
partition: invalidPartition,
|
||||
label: 'Invalid',
|
||||
source: null
|
||||
}
|
||||
]
|
||||
})
|
||||
fsState.present.add('/staged/evil')
|
||||
|
||||
installModuleMocks(fsState)
|
||||
const { browserSessionRegistry } = await import('./browser-session-registry')
|
||||
|
||||
browserSessionRegistry.applyPendingCookieImport()
|
||||
|
||||
const written = JSON.parse(fsState.files.get(META_PATH) ?? '{}')
|
||||
expect(written.pendingCookieImports).toEqual({})
|
||||
expect(fsState.present.has('/outside/Cookies')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -192,10 +192,14 @@ class BrowserSessionRegistry {
|
|||
if (pendingEntries.length === 0) {
|
||||
return
|
||||
}
|
||||
const knownPartitions = new Set([
|
||||
ORCA_BROWSER_PARTITION,
|
||||
...meta.profiles.map((p) => p.partition)
|
||||
])
|
||||
// Why: replay writes to partition-derived file paths, so corrupted
|
||||
// metadata must pass the same validation as the webview allowlist.
|
||||
const knownPartitions = new Set([ORCA_BROWSER_PARTITION])
|
||||
for (const profile of meta.profiles) {
|
||||
if (BrowserSessionRegistry.isValidPersistedProfile(profile)) {
|
||||
knownPartitions.add(profile.partition)
|
||||
}
|
||||
}
|
||||
const remainingEntries = { ...meta.pendingCookieImports }
|
||||
|
||||
for (const [partition, stagedPath] of pendingEntries) {
|
||||
|
|
@ -426,17 +430,24 @@ class BrowserSessionRegistry {
|
|||
// registering anything.
|
||||
private static readonly PARTITION_RE = /^persist:orca-browser-session-[\da-f-]{36}$/
|
||||
|
||||
private static isValidPersistedProfile(profile: unknown): profile is BrowserSessionProfile {
|
||||
if (!profile || typeof profile !== 'object') {
|
||||
return false
|
||||
}
|
||||
const candidate = profile as Partial<BrowserSessionProfile>
|
||||
return (
|
||||
candidate.id !== 'default' &&
|
||||
candidate.scope !== 'default' &&
|
||||
typeof candidate.id === 'string' &&
|
||||
typeof candidate.partition === 'string' &&
|
||||
typeof candidate.label === 'string' &&
|
||||
BrowserSessionRegistry.PARTITION_RE.test(candidate.partition)
|
||||
)
|
||||
}
|
||||
|
||||
hydrateFromPersisted(profiles: BrowserSessionProfile[]): void {
|
||||
for (const profile of profiles) {
|
||||
if (profile.id === 'default' || profile.scope === 'default') {
|
||||
continue
|
||||
}
|
||||
if (
|
||||
typeof profile.id !== 'string' ||
|
||||
typeof profile.partition !== 'string' ||
|
||||
typeof profile.label !== 'string' ||
|
||||
!BrowserSessionRegistry.PARTITION_RE.test(profile.partition)
|
||||
) {
|
||||
if (!BrowserSessionRegistry.isValidPersistedProfile(profile)) {
|
||||
continue
|
||||
}
|
||||
this.profiles.set(profile.id, profile)
|
||||
|
|
|
|||
Loading…
Reference in New Issue