From 95337a349a68693f562f142352834620558a5df4 Mon Sep 17 00:00:00 2001 From: Maksim Soltan Date: Wed, 1 Apr 2026 07:54:25 -0700 Subject: [PATCH] fix: validate saved URLs before navigating in restoreState restoreState() restored page URLs from the browse state file (~/.gstack/browse.json) without validation. The state file is user-writable and persists across sessions. A tampered or maliciously crafted state file could navigate the browser to: - file:// URIs (read local files) - cloud metadata endpoints (169.254.169.254) - javascript: URIs validateNavigationUrl() is already imported and used by goto commands. Apply the same validation here before restoring saved page URLs. Invalid URLs are skipped gracefully with a log message. Closes #674 --- browse/src/browser-manager.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/browse/src/browser-manager.ts b/browse/src/browser-manager.ts index f4ade9e1e..f13338df8 100644 --- a/browse/src/browser-manager.ts +++ b/browse/src/browser-manager.ts @@ -694,7 +694,15 @@ export class BrowserManager { this.wirePageEvents(page); if (saved.url) { - await page.goto(saved.url, { waitUntil: 'domcontentloaded', timeout: 15000 }).catch(() => {}); + // Validate the saved URL before navigating — the state file is user-writable and + // a tampered URL could navigate to cloud metadata endpoints or file:// URIs. + try { + await validateNavigationUrl(saved.url); + await page.goto(saved.url, { waitUntil: 'domcontentloaded', timeout: 15000 }).catch(() => {}); + } catch { + // Invalid URL in saved state — skip navigation, leave blank page + console.log(`[browse] restoreState: skipping unsafe URL: ${saved.url}`); + } } if (saved.storage) {