summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTobias Järvelöv <tobias.jarvelov@mullvad.net>2025-04-02 16:45:53 +0200
committerTobias Järvelöv <tobias.jarvelov@mullvad.net>2025-05-19 12:01:45 +0200
commitd57f99b62f6c1e5b2f6358ae3558a046fdcdda42 (patch)
tree50a0d249af2494b50e973c0a52e96b7f919831a9
parent91cf9c7de815f41ec3ea6adb84254497a7dfa084 (diff)
downloadmullvadvpn-d57f99b62f6c1e5b2f6358ae3558a046fdcdda42.tar.xz
mullvadvpn-d57f99b62f6c1e5b2f6358ae3558a046fdcdda42.zip
Add flipping of electron fuses
We want to disable the possibility to pass --inspect to the production build as this opens up for arbitrary code execution.
-rw-r--r--desktop/packages/mullvad-vpn/tasks/distribution.js47
1 files changed, 43 insertions, 4 deletions
diff --git a/desktop/packages/mullvad-vpn/tasks/distribution.js b/desktop/packages/mullvad-vpn/tasks/distribution.js
index a4b3dc84f5..3c8f2a7315 100644
--- a/desktop/packages/mullvad-vpn/tasks/distribution.js
+++ b/desktop/packages/mullvad-vpn/tasks/distribution.js
@@ -3,6 +3,7 @@ const fs = require('fs');
const builder = require('electron-builder');
const { Arch } = require('electron-builder');
const { execFileSync } = require('child_process');
+const { flipFuses, FuseVersion, FuseV1Options } = require('@electron/fuses');
const noCompression = process.argv.includes('--no-compression');
const shouldNotarize = process.argv.includes('--notarize');
@@ -20,6 +21,28 @@ function getOptionValue(option) {
}
}
+// Adapted from example usages in this Github issue:
+// https://github.com/electron-userland/electron-builder/issues/6365
+async function flipElectronFuses(context) {
+ const { arch, appOutDir, electronPlatformName } = context;
+
+ const fileName = {
+ darwin: 'Mullvad VPN.app',
+ linux: 'mullvad-vpn',
+ win32: 'Mullvad VPN.exe',
+ }[electronPlatformName];
+
+ const electronBinaryPath = path.join(appOutDir, fileName);
+ const resetAdHocDarwinSignature =
+ electronPlatformName === 'darwin' && arch === builder.Arch.arm64; // necessary for building on Apple Silicon
+
+ await flipFuses(electronBinaryPath, {
+ version: FuseVersion.V1,
+ resetAdHocDarwinSignature,
+ [FuseV1Options.EnableNodeCliInspectArguments]: false,
+ });
+}
+
function newConfig() {
return {
appId: 'net.mullvad.vpn',
@@ -61,7 +84,23 @@ function newConfig() {
],
// Make sure that all files declared in "extraResources" exists and abort if they don't.
- afterPack: (context) => {
+ afterPack: async (context) => {
+ const isMac = context.electronPlatformName === 'darwin';
+ const isMacUniversal = isMac && context.arch === builder.Arch.universal;
+
+ if (
+ // Flip fuses for non-MacOS platforms
+ !isMac ||
+ // Flip fuses for all MacOS platforms if universal flag
+ // is not set
+ !universal ||
+ // Only flip fuses for universal MacOS package,
+ // when the universal flag is set
+ isMacUniversal
+ ) {
+ await flipElectronFuses(context);
+ }
+
if (context.arch !== Arch.universal) {
const resources = context.packager.platformSpecificBuildOptions.extraResources;
for (const resource of resources) {
@@ -376,8 +415,8 @@ function packMac() {
await removeNseventforwarderNativeModules();
config.beforePack?.(context);
},
- afterPack: (context) => {
- config.afterPack?.(context);
+ afterPack: async (context) => {
+ await config.afterPack?.(context);
if (context.arch !== Arch.universal) {
delete process.env.TARGET_TRIPLE;
@@ -436,7 +475,7 @@ function packLinux() {
return true;
},
afterPack: async (context) => {
- config.afterPack?.(context);
+ await config.afterPack?.(context);
const sourceExecutable = path.join(context.appOutDir, 'mullvad-vpn');
const targetExecutable = path.join(context.appOutDir, 'mullvad-gui');