Skip to content

Commit

Permalink
feat(Desktop): Harden security based on best practices
Browse files Browse the repository at this point in the history
Implement several security checks based on https://github.com/doyensec/electronegativity/wiki
  • Loading branch information
alex-ketch committed Jun 29, 2021
1 parent 77fcd7d commit a210883
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 10 deletions.
2 changes: 1 addition & 1 deletion desktop/src/main/config/window.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BrowserWindow } from 'electron'
import { registerConfigHandlers, removeConfigHandlers } from '.'
import { createWindow } from '../../app/window'
import { i18n } from '../../i18n'
import { createWindow } from '../window'

let settingsWindow: BrowserWindow | null

Expand Down
4 changes: 2 additions & 2 deletions desktop/src/main/launcher/window.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { BrowserWindow } from 'electron'
import { registerLauncherHandlers, removeLauncherHandlers } from '.'
import { createWindow } from '../../app/window'
import { registerProjectHandlers } from '../project'
import { createWindow } from '../window'

let launcherWindow: BrowserWindow | null

Expand All @@ -20,7 +20,7 @@ export const openLauncherWindow = () => {
maxWidth: 1200,
minHeight: 350,
minWidth: 600,
center: true
center: true,
})

launcherWindow.on('closed', () => {
Expand Down
4 changes: 2 additions & 2 deletions desktop/src/main/onboarding/window.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { BrowserWindow } from 'electron'
import { registerOnboardingHandlers, removeOnboaringHandlers } from '.'
import { createWindow } from '../../app/window'
import { i18n } from '../../i18n'
import { registerConfigHandlers, removeConfigHandlers } from '../config'
import { registerLauncherHandlers, removeLauncherHandlers } from '../launcher'
import { createWindow } from '../window'

let onboardingWindow: BrowserWindow | null

Expand All @@ -20,7 +20,7 @@ export const openOnboardingWindow = () => {
show: false,
title: i18n.t('onboarding.title'),
fullscreenable: false,
center: true
center: true,
})

onboardingWindow.on('closed', () => {
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/main/project/window.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { parse } from 'path'
import { projects } from 'stencila'
import { registerProjectHandlers, removeProjectHandlers } from '.'
import { createWindow } from '../../app/window'
import { registerDocumentHandlers, removeDocoumentHandlers } from '../document'
import { createWindow } from '../window'

const getProjectName = (path: string): string => parse(path).base

Expand Down
11 changes: 7 additions & 4 deletions desktop/src/app/window.ts → desktop/src/main/window/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { app, BrowserWindow, BrowserWindowConstructorOptions } from 'electron'
import { i18n } from '../i18n'
import { scheme } from '../main/app-protocol'
import { i18n } from '../../i18n'
import { scheme } from '../app-protocol'
import { hardenWindow } from './security'

// declare const MAIN_WINDOW_WEBPACK_ENTRY: string
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string
Expand All @@ -23,8 +24,8 @@ export const createWindow = (
contextIsolation: true, // protect against prototype pollution
enableRemoteModule: false,
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
additionalArguments: [`storePath:${app.getPath('userData')}`]
}
additionalArguments: [`storePath:${app.getPath('userData')}`],
},
})

win.loadURL(
Expand All @@ -36,5 +37,7 @@ export const createWindow = (
win.webContents.openDevTools()
}

hardenWindow(win)

return win
}
46 changes: 46 additions & 0 deletions desktop/src/main/window/security.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { BrowserWindow } from 'electron'
import { scheme } from '../app-protocol'

const isTrustedOrigin = (url: string): boolean =>
url.startsWith('http://localhost') || url.startsWith(`${scheme}://rse`)

// Enable security best practices
// @see: https://github.com/doyensec/electronegativity/wiki
export const hardenWindow = (win: BrowserWindow) => {
// @see: https://github.com/doyensec/electronegativity/wiki/LIMIT_NAVIGATION_JS_CHECK
win.webContents.on('new-window', (e, url) => {
if (!isTrustedOrigin(url)) {
e.preventDefault()
}
})

win.webContents.on('will-navigate', (e, url) => {
if (!isTrustedOrigin(url)) {
e.preventDefault()
}
})

win.webContents.setWindowOpenHandler(({ url }) => {
if (!isTrustedOrigin(url)) {
return { action: 'deny' }
}

return {
action: 'allow',
}
})

// https://github.com/doyensec/electronegativity/wiki/PERMISSION_REQUEST_HANDLER_JS_CHECK
win.webContents.session.setPermissionRequestHandler(
(webContents, permission, callback) => {
if (
!isTrustedOrigin(webContents.getURL()) &&
permission === 'openExternal'
) {
return callback(false)
} else {
return callback(true)
}
}
)
}

0 comments on commit a210883

Please sign in to comment.