Skip to content

Commit

Permalink
chore: enable sandbox + disable remote module in default_app
Browse files Browse the repository at this point in the history
  • Loading branch information
miniak committed Mar 10, 2019
1 parent a958eb9 commit b91251d
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 40 deletions.
22 changes: 18 additions & 4 deletions default_app/default_app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ app.on('window-all-closed', () => {
app.quit()
})

export const load = async (appUrl: string) => {
const createWindow = async (isIndex: boolean = false) => {
await app.whenReady()

const options: BrowserWindowConstructorOptions = {
Expand All @@ -18,21 +18,35 @@ export const load = async (appUrl: string) => {
backgroundColor: '#FFFFFF',
webPreferences: {
contextIsolation: true,
preload: path.resolve(__dirname, 'renderer.js'),
webviewTag: false
sandbox: true,
enableRemoteModule: false
},
useContentSize: true,
show: false
}

if (isIndex) {
options.webPreferences!.preload = path.resolve(__dirname, 'renderer.js')
}

if (process.platform === 'linux') {
options.icon = path.join(__dirname, 'icon.png')
}

mainWindow = new BrowserWindow(options)

mainWindow.on('ready-to-show', () => mainWindow!.show())

return mainWindow
}

export const loadURL = async (appUrl: string) => {
mainWindow = await createWindow()
mainWindow.loadURL(appUrl)
mainWindow.focus()
}

export const loadFile = async (appPath: string) => {
mainWindow = await createWindow(appPath === 'index.html')
mainWindow.loadFile(appPath)
mainWindow.focus()
}
2 changes: 1 addition & 1 deletion default_app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<head>
<title>Electron</title>
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'" />
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self'; connect-src 'self'" />
<link href="./styles.css" type="text/css" rel="stylesheet" />
<link href="./octicon/build.css" type="text/css" rel="stylesheet" />
</head>
Expand Down
45 changes: 29 additions & 16 deletions default_app/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { app, dialog } from 'electron'
import { app, dialog, ipcMain } from 'electron'

import * as fs from 'fs'
import * as path from 'path'
Expand Down Expand Up @@ -73,6 +73,23 @@ if (option.modules.length > 0) {
Module._preloadModules(option.modules)
}

function getElectronPath () {
// Find the shortest path to the electron binary
const absoluteElectronPath = process.execPath
const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath)
return absoluteElectronPath.length < relativeElectronPath.length
? absoluteElectronPath
: relativeElectronPath
}

ipcMain.on('get-electron-path', (event) => {
try {
event.returnValue = getElectronPath()
} catch {
event.returnValue = null
}
})

function loadApplicationPackage (packagePath: string) {
// Add a flag indicating app is started from default app.
Object.defineProperty(process, 'defaultApp', {
Expand Down Expand Up @@ -129,9 +146,14 @@ function showErrorMessage (message: string) {
process.exit(1)
}

async function loadApplicationByUrl (appUrl: string) {
const { load } = await import('./default_app')
load(appUrl)
async function loadApplicationByURL (appUrl: string) {
const { loadURL } = await import('./default_app')
loadURL(appUrl)
}

async function loadApplicationByFile (appPath: string) {
const { loadFile } = await import('./default_app')
loadFile(appPath)
}

function startRepl () {
Expand All @@ -156,13 +178,9 @@ if (option.file && !option.webdriver) {
const protocol = url.parse(file).protocol
const extension = path.extname(file)
if (protocol === 'http:' || protocol === 'https:' || protocol === 'file:' || protocol === 'chrome:') {
loadApplicationByUrl(file)
loadApplicationByURL(file)
} else if (extension === '.html' || extension === '.htm') {
loadApplicationByUrl(url.format({
protocol: 'file:',
slashes: true,
pathname: path.resolve(file)
}))
loadApplicationByFile(path.resolve(file))
} else {
loadApplicationPackage(file)
}
Expand Down Expand Up @@ -196,10 +214,5 @@ Options:
console.log(welcomeMessage)
}

const indexPath = path.join(__dirname, '/index.html')
loadApplicationByUrl(url.format({
protocol: 'file:',
slashes: true,
pathname: indexPath
}))
loadApplicationByFile('index.html')
}
27 changes: 10 additions & 17 deletions default_app/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import { remote, shell } from 'electron'
import * as fs from 'fs'
import * as path from 'path'
import { shell, ipcRenderer } from 'electron'
import * as URL from 'url'

function initialize () {
// Find the shortest path to the electron binary
const absoluteElectronPath = remote.process.execPath
const relativeElectronPath = path.relative(process.cwd(), absoluteElectronPath)
const electronPath = absoluteElectronPath.length < relativeElectronPath.length
? absoluteElectronPath
: relativeElectronPath
const electronPath = ipcRenderer.sendSync('get-electron-path')

for (const link of document.querySelectorAll<HTMLLinkElement>('a[href]')) {
// safely add `?utm_source=default_app
Expand All @@ -32,21 +25,21 @@ function initialize () {
document.querySelector<HTMLAnchorElement>('.v8-version')!.innerText = `v8 v${process.versions.v8}`
document.querySelector<HTMLAnchorElement>('.command-example')!.innerText = `${electronPath} path-to-app`

function getOcticonSvg (name: string) {
const octiconPath = path.resolve(__dirname, 'octicon', `${name}.svg`)
if (fs.existsSync(octiconPath)) {
const content = fs.readFileSync(octiconPath, 'utf8')
async function getOcticonSvg (name: string) {
try {
const response = await fetch(`octicon/${name}.svg`)
const div = document.createElement('div')
div.innerHTML = content
div.innerHTML = await response.text()
return div
} catch {
return null
}
return null
}

function loadSVG (element: HTMLSpanElement) {
async function loadSVG (element: HTMLSpanElement) {
for (const cssClass of element.classList) {
if (cssClass.startsWith('octicon-')) {
const icon = getOcticonSvg(cssClass.substr(8))
const icon = await getOcticonSvg(cssClass.substr(8))
if (icon) {
for (const elemClass of element.classList) {
icon.classList.add(elemClass)
Expand Down
4 changes: 2 additions & 2 deletions lib/sandboxed_renderer/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,15 @@ const errorUtils = require('@electron/internal/common/error-utils')
// since browserify won't try to include `electron` in the bundle, falling back
// to the `preloadRequire` function above.
function runPreloadScript (preloadSrc) {
const preloadWrapperSrc = `(function(require, process, Buffer, global, setImmediate, clearImmediate) {
const preloadWrapperSrc = `(function(require, process, Buffer, global, setImmediate, clearImmediate, exports) {
${preloadSrc}
})`

// eval in window scope
const preloadFn = binding.createPreloadScript(preloadWrapperSrc)
const { setImmediate, clearImmediate } = require('timers')

preloadFn(preloadRequire, preloadProcess, Buffer, global, setImmediate, clearImmediate)
preloadFn(preloadRequire, preloadProcess, Buffer, global, setImmediate, clearImmediate, {})
}

for (const { preloadPath, preloadSrc, preloadError } of preloadScripts) {
Expand Down

0 comments on commit b91251d

Please sign in to comment.