From 9f0cd0d2c312519b8741ad557cd514ab1921eeb0 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Sat, 25 Dec 2021 00:52:49 +0100 Subject: feat: Harden window navigation and permissions --- packages/main/src/index.ts | 60 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 5 deletions(-) (limited to 'packages/main') diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts index 0c0a585..09441ef 100644 --- a/packages/main/src/index.ts +++ b/packages/main/src/index.ts @@ -84,8 +84,9 @@ function getResourcePath(relativePath: string): string { return join(__dirname, relativePath); } +const baseUrl = `file://${__dirname}`; function getResourceUrl(relativePath: string): string { - return new URL(relativePath, `file://${__dirname}`).toString(); + return new URL(relativePath, baseUrl).toString(); } let serviceInjectRelativePath = '../../service-inject/dist/index.cjs'; @@ -103,6 +104,33 @@ let mainWindow: BrowserWindow | null = null; const store = createRootStore(); +const rendererBaseUrl = getResourceUrl('../renderer/'); +function shouldCancelMainWindowRequest(url: string, method: string): boolean { + if (method !== 'GET') { + return true; + } + let normalizedUrl: string; + try { + normalizedUrl = new URL(url).toString(); + } catch (_err) { + return true; + } + if (normalizedUrl.startsWith('devtools:')) { + return false; + } + if (isDevelopment) { + if (normalizedUrl.startsWith('chrome-extension:')) { + return false; + } + if (import.meta.env.VITE_DEV_SERVER_URL !== undefined) { + const isHttp = normalizedUrl.startsWith(import.meta.env.VITE_DEV_SERVER_URL); + const isWs = normalizedUrl.startsWith(import.meta.env.VITE_DEV_SERVER_URL.replace(/^http:/, 'ws:')); + return !isHttp && !isWs; + } + } + return !normalizedUrl.startsWith(getResourceUrl(rendererBaseUrl)); +} + function createWindow(): Promise { mainWindow = new BrowserWindow({ show: false, @@ -112,6 +140,26 @@ function createWindow(): Promise { }, }); + const { webContents } = mainWindow; + + webContents.userAgent = originalUserAgent; + + webContents.session.setPermissionRequestHandler((_webContents, _permission, callback) => { + callback(false); + }); + + webContents.session.webRequest.onBeforeRequest(({ url, method }, callback) => { + callback({ + cancel: shouldCancelMainWindowRequest(url, method), + }) + }); + + webContents.on('will-navigate', (event) => { + event.preventDefault(); + }); + + webContents.setWindowOpenHandler(() => ({ action: 'deny' })); + if (isDevelopment) { openDevToolsWhenReady(mainWindow); } @@ -120,10 +168,6 @@ function createWindow(): Promise { mainWindow?.show(); }); - const { webContents } = mainWindow; - - webContents.userAgent = originalUserAgent; - const browserView = new BrowserView({ webPreferences: { sandbox: true, @@ -198,6 +242,12 @@ function createWindow(): Promise { } }); + browserView.webContents.session.setPermissionRequestHandler( + (_webContents, _permission, callback) => { + callback(false); + } + ); + browserView.webContents.session.webRequest.onBeforeSendHeaders(({ url, requestHeaders }, callback) => { if (url.match(/^[^:]+:\/\/accounts\.google\.[^.\/]+\//)) { requestHeaders['User-Agent'] = chromelessUserAgent; -- cgit v1.2.3-54-g00ecf