CVE-2020-25019: Insufficient Verification of Data Authenticity (CWE-345)
value: jitsi-meet-electron (aka Jitsi Meet Electron) before 2.3.0 calls the Electron shell.openExternal function without verifying that the URL is for an http or https resource, in some circumstances.
CWE description: The product does not sufficiently verify the origin or authenticity of data, in a way that causes it to accept invalid data.
CVSS v3 base score: 7.5
Published: 2020-08-29T17:15Z
Repository: https://github.com/jitsi/jitsi-meet-electron
Language: JavaScript
Files changed: app/features/utils/openExternalLink.js, app/preload/preload.js, main.js, package.json
Commit date: 2020-06-30 11:16:55 +0200
Commit message: Share logic for opening external links

Diff: diff --git a/app/features/utils/openExternalLink.js b/app/features/utils/openExternalLink.js
new file mode 100644
index 0000000..7694b53
--- /dev/null
+++ b/app/features/utils/openExternalLink.js
@@ -0,0 +1,25 @@
+const { shell } = require('electron');
+const url = require('url');
+
+
+const protocolRegex = /^https?:/i;
+
+/**
+ * Opens the given link in an external browser.
+ *
+ * @param {string} link - The link (URL) that should be opened in the external browser.
+ * @returns {void}
+ */
+export function openExternalLink(link) {
+    let u;
+
+    try {
+        u = url.parse(link);
+    } catch (e) {
+        return;
+    }
+
+    if (protocolRegex.test(u.protocol)) {
+        shell.openExternal(link);
+    }
+}
diff --git a/app/preload/preload.js b/app/preload/preload.js
index 538b82f..ccc65cc 100644
--- a/app/preload/preload.js
+++ b/app/preload/preload.js
@@ -1,42 +1,19 @@
 const createElectronStorage = require('redux-persist-electron-storage');
-const { ipcRenderer, shell, remote } = require('electron');
+const { ipcRenderer, remote } = require('electron');
 const os = require('os');
-const url = require('url');
-
 const jitsiMeetElectronUtils = require('jitsi-meet-electron-utils');
+const { openExternalLink } = require('../features/utils/openExternalLink');
 
-const protocolRegex = /^https?:/i;
-
-/**
- * Opens the given link in an external browser.
- *
- * @param {string} link - The link (URL) that should be opened in the external browser.
- * @returns {void}
- */
-function openExternalLink(link) {
-    let u;
-
-    try {
-        u = url.parse(link);
-    } catch (e) {
-        return;
-    }
-
-    if (protocolRegex.test(u.protocol)) {
-        shell.openExternal(link);
-    }
-}
 
 const whitelistedIpcChannels = [ 'protocol-data-msg', 'renderer-ready' ];
 
 window.jitsiNodeAPI = {
     createElectronStorage,
     osUserInfo: os.userInfo,
     openExternalLink,
     jitsiMeetElectronUtils,
-    shellOpenExternal: shell.openExternal,
     getLocale: remote.app.getLocale,
     ipc: {
         on: (channel, listener) => {
             if (!whitelistedIpcChannels.includes(channel)) {
                 return;
diff --git a/main.js b/main.js
index 0ca6cde..137fe8d 100644
--- a/main.js
+++ b/main.js
@@ -2,12 +2,11 @@
 
 const {
     BrowserWindow,
     Menu,
     app,
-    ipcMain,
-    shell
+    ipcMain
 } = require('electron');
 const contextMenu = require('electron-context-menu');
 const debug = require('electron-debug');
 const isDev = require('electron-is-dev');
 const { autoUpdater } = require('electron-updater');
@@ -20,10 +19,11 @@ const {
     setupScreenSharingMain
 } = require('jitsi-meet-electron-utils');
 const path = require('path');
 const URL = require('url');
 const config = require('./app/features/config');
+const { openExternalLink } = require('./app/features/utils/openExternalLink');
 
 const showDevTools = Boolean(process.env.SHOW_DEV_TOOLS) || (process.argv.indexOf('--show-dev-tools') > -1);
 
 // We need this because of https://github.com/electron/electron/issues/18214
 app.commandLine.appendSwitch('disable-site-isolation-trials');
@@ -209,11 +209,11 @@ function createJitsiMeetWindow() {
     mainWindow.webContents.on('new-window', (event, url, frameName) => {
         const target = getPopupTarget(url, frameName);
 
         if (!target || target === 'browser') {
             event.preventDefault();
-            shell.openExternal(url);
+            openExternalLink(url);
         }
     });
     mainWindow.on('closed', () => {
         mainWindow = null;
     });
diff --git a/package.json b/package.json
index ba7dbb9..015bab8 100644
--- a/package.json
+++ b/package.json
@@ -13,12 +13,12 @@
     "dist": "npm run build && electron-builder",
     "postinstall": "patch-package && electron-builder install-app-deps",
     "validate": "npm ls",
     "watch": "webpack --config ./webpack.renderer.js --mode development --watch --watch-poll"
   },
-  "engines" : {
-    "node" : ">=12.0.0"
+  "engines": {
+    "node": ">=12.0.0"
   },
   "build": {
     "appId": "org.jitsi.jitsi-meet",
     "productName": "Jitsi Meet",
     "generateUpdatesFilesForAllChannels": true,

Vulnerable code: const { ipcRenderer, shell, remote } = require('electron');
const url = require('url');

const protocolRegex = /^https?:/i;

/**
 * Opens the given link in an external browser.
 *
 * @param {string} link - The link (URL) that should be opened in the external browser.
 * @returns {void}
 */
function openExternalLink(link) {
    let u;

    try {
        u = url.parse(link);
    } catch (e) {
        return;
    }

    if (protocolRegex.test(u.protocol)) {
        shell.openExternal(link);
    }
}
    shellOpenExternal: shell.openExternal,
    ipcMain,
    shell
            shell.openExternal(url);
  "engines" : {
    "node" : ">=12.0.0"
Fixed code: const { shell } = require('electron');
const url = require('url');


const protocolRegex = /^https?:/i;

/**
 * Opens the given link in an external browser.
 *
 * @param {string} link - The link (URL) that should be opened in the external browser.
 * @returns {void}
 */
export function openExternalLink(link) {
    let u;

    try {
        u = url.parse(link);
    } catch (e) {
        return;
    }

    if (protocolRegex.test(u.protocol)) {
        shell.openExternal(link);
    }
}
const { ipcRenderer, remote } = require('electron');
const { openExternalLink } = require('../features/utils/openExternalLink');
    ipcMain
const { openExternalLink } = require('./app/features/utils/openExternalLink');
            openExternalLink(url);
  "engines": {
    "node": ">=12.0.0"