[Mm 37198] enable global sandboxing to increase security (#1667)
* prevent creating new windows from popup windows * enable sandbox * fix windows detection logic * disable on testing environment Co-authored-by: = <=>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
// See LICENSE.txt for license information.
|
||||
import fs from 'fs';
|
||||
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
import {EventEmitter} from 'events';
|
||||
@@ -43,11 +44,17 @@ export default class Config extends EventEmitter {
|
||||
defaultConfigData?: ConfigType;
|
||||
buildConfigData?: BuildConfig;
|
||||
localConfigData?: ConfigType;
|
||||
useNativeWindow: boolean;
|
||||
|
||||
constructor(configFilePath: string) {
|
||||
super();
|
||||
this.configFilePath = configFilePath;
|
||||
this.registryConfig = new RegistryConfig();
|
||||
try {
|
||||
this.useNativeWindow = os.platform() === 'win32' && (parseInt(os.release().split('.')[0], 10) < 10);
|
||||
} catch {
|
||||
this.useNativeWindow = false;
|
||||
}
|
||||
}
|
||||
|
||||
// separating constructor from init so main can setup event listeners
|
||||
@@ -315,7 +322,7 @@ export default class Config extends EventEmitter {
|
||||
*/
|
||||
regenerateCombinedConfigData = () => {
|
||||
// combine all config data in the correct order
|
||||
this.combinedData = Object.assign({}, this.defaultConfigData, this.localConfigData, this.buildConfigData, this.registryConfigData);
|
||||
this.combinedData = Object.assign({}, this.defaultConfigData, this.localConfigData, this.buildConfigData, this.registryConfigData, {useNativeWindow: this.useNativeWindow});
|
||||
|
||||
// remove unecessary data pulled from default and build config
|
||||
delete this.combinedData!.defaultTeams;
|
||||
|
@@ -190,6 +190,9 @@ function initializeBeforeAppReady() {
|
||||
log.error('No config loaded');
|
||||
return;
|
||||
}
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
app.enableSandbox();
|
||||
}
|
||||
certificateStore = new CertificateStore(path.resolve(app.getPath('userData'), 'certificate.json'));
|
||||
trustedOriginsStore = new TrustedOriginsStore(path.resolve(app.getPath('userData'), 'trustedOrigins.json'));
|
||||
trustedOriginsStore.load();
|
||||
|
@@ -4,7 +4,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import os from 'os';
|
||||
import {ipcRenderer, contextBridge} from 'electron';
|
||||
|
||||
contextBridge.exposeInMainWorld('ipcRenderer', {
|
||||
@@ -13,10 +12,6 @@ contextBridge.exposeInMainWorld('ipcRenderer', {
|
||||
invoke: ipcRenderer.invoke,
|
||||
});
|
||||
|
||||
contextBridge.exposeInMainWorld('os', {
|
||||
isWindows10: os.platform() === 'win32' && os.release().startsWith('10'),
|
||||
});
|
||||
|
||||
contextBridge.exposeInMainWorld('process', {
|
||||
platform: process.platform,
|
||||
env: {
|
||||
|
@@ -82,6 +82,12 @@ const generateDidStartNavigation = (getServersFunction: () => TeamWithTabs[]) =>
|
||||
};
|
||||
};
|
||||
|
||||
const denyNewWindow = (event: Event, url: string) => {
|
||||
event.preventDefault();
|
||||
log.warn(`Prevented popup window to open a new window to ${url}.`);
|
||||
return null;
|
||||
};
|
||||
|
||||
const generateNewWindowListener = (getServersFunction: () => TeamWithTabs[], spellcheck?: boolean) => {
|
||||
return (event: Event, url: string) => {
|
||||
const parsedURL = urlUtils.parseURL(url);
|
||||
@@ -160,12 +166,14 @@ const generateNewWindowListener = (getServersFunction: () => TeamWithTabs[], spe
|
||||
show: false,
|
||||
center: true,
|
||||
webPreferences: {
|
||||
nativeWindowOpen: true,
|
||||
nodeIntegration: process.env.NODE_ENV === 'test',
|
||||
contextIsolation: process.env.NODE_ENV !== 'test',
|
||||
spellcheck: (typeof spellcheck === 'undefined' ? true : spellcheck),
|
||||
enableRemoteModule: process.env.NODE_ENV === 'test',
|
||||
},
|
||||
});
|
||||
popupWindow.webContents.on('new-window', denyNewWindow);
|
||||
popupWindow.once('ready-to-show', () => {
|
||||
popupWindow!.show();
|
||||
});
|
||||
|
@@ -64,6 +64,7 @@ type Props = {
|
||||
openMenu: () => void;
|
||||
darkMode: boolean;
|
||||
appName: string;
|
||||
useNativeWindow: boolean;
|
||||
};
|
||||
|
||||
type State = {
|
||||
@@ -358,7 +359,7 @@ export default class MainPage extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
let titleBarButtons;
|
||||
if (window.os.isWindows10) {
|
||||
if (window.process.platform === 'win32' && !this.props.useNativeWindow) {
|
||||
titleBarButtons = (
|
||||
<span className='title-bar-btns'>
|
||||
<div
|
||||
|
@@ -126,6 +126,7 @@ class Root extends React.PureComponent<Record<string, never>, State> {
|
||||
openMenu={this.openMenu}
|
||||
darkMode={config.darkMode}
|
||||
appName={config.appName}
|
||||
useNativeWindow={config.useNativeWindow}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -102,6 +102,8 @@ export type RegistryConfig = {
|
||||
export type CombinedConfig = ConfigV3 & BuildConfig & {
|
||||
registryTeams: Team[];
|
||||
appName: string;
|
||||
useNativeWindow: boolean;
|
||||
|
||||
}
|
||||
|
||||
export type LocalConfiguration = Config & {
|
||||
|
@@ -10,9 +10,6 @@ declare global {
|
||||
on: (channel: string, listener: (...args: any[]) => void) => void;
|
||||
invoke: typeof ipcRenderer.invoke;
|
||||
};
|
||||
os: {
|
||||
isWindows10: boolean;
|
||||
};
|
||||
process: {
|
||||
platform: NodeJS.Platform;
|
||||
env: {
|
||||
|
Reference in New Issue
Block a user