diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2021-03-12 10:19:14 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2021-03-24 16:42:37 +0100 |
| commit | 4437de21ab18a3ede2d067ce90db3c31d0865d82 (patch) | |
| tree | 2c1da7073862407291d14acc1c1322f1d207bd1c /gui/src | |
| parent | a34620a0a6bf807bb465597779051566d06aab20 (diff) | |
| download | mullvadvpn-4437de21ab18a3ede2d067ce90db3c31d0865d82.tar.xz mullvadvpn-4437de21ab18a3ede2d067ce90db3c31d0865d82.zip | |
Prevent renderer access to files outside of build directory
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/main/index.ts | 69 |
1 files changed, 47 insertions, 22 deletions
diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts index d9acc95a42..efbf9a4aa3 100644 --- a/gui/src/main/index.ts +++ b/gui/src/main/index.ts @@ -386,8 +386,11 @@ class ApplicationMain { // fetching. https://github.com/electron/electron/issues/22995 session.defaultSession.setSpellCheckerDictionaryDownloadURL('https://00.00/'); + // Blocks scripts in the renderer process from asking for any permission. this.blockPermissionRequests(); + // Blocks any http(s) and file requests that aren't supposed to happen. this.blockRequests(); + // Blocks navigation since it's not needed. this.blockNavigation(); this.translations = this.updateCurrentLocale(); @@ -1422,30 +1425,52 @@ class ApplicationMain { // renderer process are blocked to protect against the potential threat of malicious third party // dependencies. There are a few exceptions which are described further down. private blockRequests() { - session.defaultSession.webRequest.onBeforeRequest( - { urls: ['*://*/*'] }, - (details, callback) => { - if ( - process.env.NODE_ENV === 'development' && - // Local web server providing assests (index.html, index.js and css files) - (details.url.startsWith('http://localhost:8080/') || - // Automatic reloading performed by the browser-sync module - details.url.startsWith('http://localhost:35829/browser-sync/') || - // Downloading of React and Redux developer tools. - details.url.startsWith('https://clients2.google.com') || - details.url.startsWith('https://clients2.googleusercontent.com')) - ) { - callback({}); - } else { - log.error(`${details.method} request blocked: ${details.url}`); - callback({ cancel: true }); + session.defaultSession.webRequest.onBeforeRequest((details, callback) => { + if (this.allowFileAccess(details.url) || this.allowDevelopmentRequest(details.url)) { + callback({}); + } else { + log.error(`${details.method} request blocked: ${details.url}`); + callback({ cancel: true }); - // Throw error in development to notify since this should never happen. - if (process.env.NODE_ENV === 'development') { - throw new Error('Web request blocked'); - } + // Throw error in development to notify since this should never happen. + if (process.env.NODE_ENV === 'development') { + throw new Error('Web request blocked'); } - }, + } + }); + } + + private allowFileAccess(url: string): boolean { + const buildDir = path.normalize(path.join(path.resolve(__dirname), '..', '..')); + + if (url.startsWith('file:')) { + // Extract the path from the URL + let filePath = decodeURI(new URL(url).pathname); + if (process.platform === 'win32') { + // Windows paths shouldn't start with a '/' + filePath = filePath.replace(/^\//, ''); + } + filePath = path.resolve(filePath); + + return !path.relative(buildDir, filePath).includes('..'); + } else { + return false; + } + } + + private allowDevelopmentRequest(url: string): boolean { + return ( + process.env.NODE_ENV === 'development' && + // Local web server providing assests (index.html, index.js and css files) + (url.startsWith('http://localhost:8080/') || + // Automatic reloading performed by the browser-sync module + url.startsWith('ws://localhost:35829/browser-sync') || + url.startsWith('http://localhost:35829/browser-sync/') || + // Downloading of React and Redux developer tools. + url.startsWith('devtools://devtools/') || + url.startsWith('chrome-extension://') || + url.startsWith('https://clients2.google.com') || + url.startsWith('https://clients2.googleusercontent.com')) ); } |
