Browse Source

fix: block custom window.open when nativeWindowOpen is true (#23188)

Jeremy Apthorp 5 years ago
parent
commit
c798a6e5d1
2 changed files with 34 additions and 0 deletions
  1. 6 0
      lib/browser/guest-window-manager.js
  2. 28 0
      spec-main/chromium-spec.ts

+ 6 - 0
lib/browser/guest-window-manager.js

@@ -219,6 +219,12 @@ const canAccessWindow = function (sender, target) {
 
 // Routed window.open messages with raw options
 ipcMainInternal.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, url, frameName, features) => {
+  // This should only be allowed for senders that have nativeWindowOpen: false
+  const webPreferences = event.sender.getLastWebPreferences();
+  if (webPreferences.nativeWindowOpen || webPreferences.sandbox) {
+    event.returnValue = null;
+    throw new Error('GUEST_WINDOW_MANAGER_WINDOW_OPEN denied: expected native window.open');
+  }
   if (url == null || url === '') url = 'about:blank';
   if (frameName == null) frameName = '';
   if (features == null) features = '';

+ 28 - 0
spec-main/chromium-spec.ts

@@ -654,6 +654,34 @@ describe('chromium features', () => {
       const [, window] = await emittedOnce(app, 'browser-window-created');
       expect(window.getTitle()).to.equal('__proto__');
     });
+
+    it('denies custom open when nativeWindowOpen: true', async () => {
+      const w = new BrowserWindow({
+        show: false,
+        webPreferences: {
+          contextIsolation: false,
+          nodeIntegration: true,
+          nativeWindowOpen: true
+        }
+      });
+      w.loadURL('about:blank');
+
+      const previousListeners = process.listeners('uncaughtException');
+      process.removeAllListeners('uncaughtException');
+      try {
+        const uncaughtException = new Promise<Error>(resolve => {
+          process.once('uncaughtException', resolve);
+        });
+        expect(await w.webContents.executeJavaScript(`(${function () {
+          const ipc = process.electronBinding('ipc').ipc;
+          return ipc.sendSync(true, 'ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', ['', '', ''])[0];
+        }})()`)).to.be.null();
+        const exception = await uncaughtException;
+        expect(exception.message).to.match(/denied: expected native window\.open/);
+      } finally {
+        previousListeners.forEach(l => process.on('uncaughtException', l));
+      }
+    });
   });
 
   describe('window.opener', () => {