electron: `will-navigate` event not fired when in sandbox mode

Thanks for Electron! Amazing project 😃

  • Electron version: 1.6.2
  • Operating system: macOS Sierra (10.12.3)

It happens when BrowserWindow is opened with sandbox: true. It might be on purpose, but I couldn’t find any Electron/Chromium documentation that explains why. So I’m suspecting it’s a bug. I can submit a PR with a failing test to this repo if you agree that it’s a bug.

Expected behavior

webContentswill-navigate event should fire when user reloads page fx.

Actual behavior

It does not fire.

How to reproduce

package.json:

{
  "name": "electron-sandbox-will-navigate-bug",
  "version": "0.0.0",
  "main": "main.js",
  "dependencies": {
    "electron": "^1.6.2"
  }
}

main.js:

const {app, BrowserWindow} = require('electron')
const path = require('path')

app.on('ready', function() {
  const win = new BrowserWindow({
    webPreferences: {
      sandbox: true
    }
  })

  const {webContents} = win
  webContents.on('will-navigate', () => {
    console.log('will-navigate')
  })
  webContents.on('did-navigate', () => {
    console.log('did-navigate')
  })

  win.loadURL('file://' + path.join(__dirname, 'index.html'))
})

index.html:

<!doctype html>
<html>
  <body>
    <button onclick="window.location.reload()">Reload</button>
  </body>
</html>

Perform these steps:

  • Run npm install
  • Run ./node_modules/.bin/electron .
  • Click the Reload button in the browser window
  • Observe the Terminal output

Expected output:

did-navigate
will-navigate
did-navigate

Actual output:

did-navigate
did-navigate

(will-navigate is not fired).

If you outcomment the line sandbox:true in main.js, then it works as expected.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 9
  • Comments: 24 (10 by maintainers)

Commits related to this issue

Most upvoted comments

There are 6+ months of comments confirming it is still present in versions post-4.2, please do not close this issue again.

No news, but i did some brief digging and it seems the sandbox codepath never invokes OpenURLForTab which is what causes this. Still working on the why and the fix.

@codebytere This bug still exists in v3.0.0, so please reopen the issue.

The issue is reproducible in every Electron version since the introduction of the sandbox flag (in v1.4.2) up to the latest stable Electron release (v8.0).

Because of this, every implementation relying on will-navigate to abort navigation for security reasons will stop working once sandbox will be enabled. Because this behavior is dangerous and undocumented, I believe it should be treated as a security issue.

As a possible workaround in case of sandboxed apps, the webRequest.onBeforeRequest or webRequest.onBeforeSendHeaders together with webRequest.onBeforeRedirect functions can be used in the app.on('ready') handler to intercept the navigation events:

  const ses = session.defaultSession
  const domainToAllow = 'https://www.doyensec.com/‘

  ses.webRequest.onBeforeRequest((details, callback) => {
    if (!details.url.startsWith(domainToAllow)) {
      console.log(`blocked the request to ${details.url}`)
      callback({ cancel: true })
    } else { 
      console.log(`allowed the request to ${details.url}`)
      callback({})
    }
  })

It would also be possible to use webRequest.onHeadersReceived and webRequest.onResponseStarted events to prevent external content from being rendered, but that approach would nonetheless perform the request, which is undesirable. See https://www.electronjs.org/docs/api/web-request for more.

As well as in v5 beta

Still exists in 4.* Is there any workaround to make it works?

Perhaps this should rely on ShouldTransferNavigation instead?

I did some more in-depth digging to understand when OpenURLFromTab was called. It appears it was only called when a new process was created. I’ve created a pull request that fixes the tactical issue.

same issue in 5.0.6

We still observe this on 5.0.5. Any updates?

The workaround of disabling the cmd-R shortcut is not applicable for us, as we are trying to prevent link navigations (i.e. not just page reloads) for security and user experience purposes.

you can “fix” this by doing the following:

electron.globalShortcut.register('CommandOrControl+R', () => {
    console.log('CommandOrControl+R is pressed')
})

but note that it disables CMD+R across all applications the user has open (e.g. they won’t be able to reload a page in Chrome using CMD+R)

I can reproduce this too, will-navigate is never fired, which makes aborting navigations for security reasons a hassle. Also nothing in the docs state that sandboxing will prevent the firing of this event.