Skip to content

Commit 5ae032c

Browse files
committed
Limit electron perms to our trusted origin for defense in depth
As noted in the comment: this shouldn't ever matter, but if somehow an untrusted page does get loaded into the app somehow, this ensures it can't directly access any advanced permissions.
1 parent 5172993 commit 5ae032c

File tree

1 file changed

+12
-6
lines changed

1 file changed

+12
-6
lines changed

src/index.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ const packageJson = require('../package.json');
3232
const isWindows = os.platform() === 'win32';
3333

3434
const APP_URL = process.env.APP_URL || 'https://app.httptoolkit.tech';
35+
const hasTrustedOrigin = (url: URL) => url.origin === APP_URL;
36+
3537
const AUTH_TOKEN = crypto.randomBytes(20).toString('base64url');
3638
const DESKTOP_VERSION = packageJson.version;
3739
const BUNDLED_SERVER_VERSION = packageJson.config['httptoolkit-server-version'];
@@ -103,6 +105,14 @@ const createWindow = (logStream: WriteStream) => {
103105
logStream.write(`${levelName}: ${message}\n`);
104106
});
105107

108+
// Limit permissions to our trusted origin only. This shouldn't be required (we don't allow loading
109+
// 3rd party sites) but it's good practice for defense-in-depth etc. We don't limit permissions
110+
// on the other hand - for *our* code, we trust it to do whatever it needs.
111+
window.webContents.session.setPermissionRequestHandler((wc, _perm, callback) => {
112+
const pageUrl = new URL(wc.getURL());
113+
return callback(hasTrustedOrigin(pageUrl));
114+
});
115+
106116
window.loadURL(APP_URL + '?' + querystring.stringify({
107117
authToken: AUTH_TOKEN,
108118
desktopVersion: DESKTOP_VERSION
@@ -204,7 +214,7 @@ if (!amMainInstance) {
204214
const parsedUrl = new URL(navigationUrl);
205215

206216
checkForUnsafeNavigation(parsedUrl);
207-
if (!isLocalNavigation(parsedUrl)) {
217+
if (!hasTrustedOrigin(parsedUrl)) {
208218
event.preventDefault();
209219
handleExternalNavigation(parsedUrl);
210220
}
@@ -213,7 +223,7 @@ if (!amMainInstance) {
213223
const parsedUrl = new URL(openDetails.url);
214224

215225
checkForUnsafeNavigation(parsedUrl);
216-
if (!isLocalNavigation(parsedUrl)) {
226+
if (!hasTrustedOrigin(parsedUrl)) {
217227
handleExternalNavigation(parsedUrl);
218228
return { action: 'deny' };
219229
} else {
@@ -268,10 +278,6 @@ if (!amMainInstance) {
268278
}
269279
}
270280

271-
function isLocalNavigation(url: URL) {
272-
return url.origin === APP_URL;
273-
}
274-
275281
function handleExternalNavigation(url: URL) {
276282
shell.openExternal(url.toString())
277283
.catch((error) => {

0 commit comments

Comments
 (0)