Skip to content

Commit 6e5531a

Browse files
committed
feat(App): Add security checks for external URLs
1 parent 38dde19 commit 6e5531a

File tree

4 files changed

+36
-2
lines changed

4 files changed

+36
-2
lines changed

src/config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,9 @@ export const SETTINGS_PATH = path.join(app.getPath('userData'), 'config');
6262

6363
// Replacing app.asar is not beautiful but unforunately necessary
6464
export const DICTIONARY_PATH = asarPath(path.join(__dirname, 'dictionaries'));
65+
66+
export const ALLOWED_PROTOCOLS = [
67+
'https:',
68+
'http:',
69+
'ftp:',
70+
];

src/helpers/url-helpers.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { URL } from 'url';
2+
3+
import { ALLOWED_PROTOCOLS } from '../config';
4+
5+
const debug = require('debug')('Franz:Helpers:url');
6+
7+
export function isValidExternalURL(url) {
8+
const parsedUrl = new URL(url);
9+
10+
const isAllowed = ALLOWED_PROTOCOLS.includes(parsedUrl.protocol);
11+
12+
debug('protocol check is', isAllowed, 'for:', url);
13+
14+
return isAllowed;
15+
}

src/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
DEFAULT_WINDOW_OPTIONS,
3535
} from './config';
3636
import { asarPath } from './helpers/asar-helpers';
37+
import { isValidExternalURL } from './helpers/url-helpers';
3738
/* eslint-enable import/first */
3839

3940
const debug = require('debug')('Franz:App');
@@ -294,7 +295,10 @@ const createWindow = () => {
294295
mainWindow.webContents.on('new-window', (e, url) => {
295296
debug('Open url', url);
296297
e.preventDefault();
297-
shell.openExternal(url);
298+
299+
if (isValidExternalURL(url)) {
300+
shell.openExternal(url);
301+
}
298302
});
299303
};
300304

src/stores/AppStore.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { getDoNotDisturb } from '@meetfranz/electron-notification-state';
88
import AutoLaunch from 'auto-launch';
99
import prettyBytes from 'pretty-bytes';
1010
import ms from 'ms';
11+
import { URL } from 'url';
1112

1213
import Store from './lib/Store';
1314
import Request from './lib/Request';
@@ -19,6 +20,7 @@ import { onVisibilityChange } from '../helpers/visibility-helper';
1920
import { getLocale } from '../helpers/i18n-helpers';
2021

2122
import { getServiceIdsFromPartitions, removeServicePartitionDirectory } from '../helpers/service-helpers.js';
23+
import { isValidExternalURL } from '../helpers/url-helpers';
2224

2325
const debug = require('debug')('Franz:AppStore');
2426

@@ -256,7 +258,14 @@ export default class AppStore extends Store {
256258
}
257259

258260
@action _openExternalUrl({ url }) {
259-
shell.openExternal(url);
261+
const parsedUrl = new URL(url);
262+
debug('open external url', parsedUrl);
263+
264+
if (isValidExternalURL(url)) {
265+
shell.openExternal(url);
266+
}
267+
268+
gaEvent('External URL', 'open', parsedUrl.host);
260269
}
261270

262271
@action _checkForUpdates() {

0 commit comments

Comments
 (0)