diff --git a/packages/desktop-electron/index.ts b/packages/desktop-electron/index.ts
index dda8cf7741e9a260c6629752a06bad254d7304ff..febd2e2cf1bc650c2eb5ead522ada60251ec101e 100644
--- a/packages/desktop-electron/index.ts
+++ b/packages/desktop-electron/index.ts
@@ -3,6 +3,7 @@ import Module from 'module';
 import path from 'path';
 
 import {
+  net,
   app,
   ipcMain,
   BrowserWindow,
@@ -17,8 +18,6 @@ import {
   SaveDialogOptions,
 } from 'electron';
 import isDev from 'electron-is-dev';
-// @ts-strict-ignore
-import fetch from 'node-fetch';
 import promiseRetry from 'promise-retry';
 
 import { getMenu } from './menu';
@@ -37,8 +36,6 @@ protocol.registerSchemesAsPrivileged([
   { scheme: 'app', privileges: { standard: true } },
 ]);
 
-global.fetch = fetch;
-
 if (!isDev || !process.env.ACTUAL_DOCUMENT_DIR) {
   process.env.ACTUAL_DOCUMENT_DIR = app.getPath('documents');
 }
@@ -63,13 +60,13 @@ function createBackgroundProcess() {
     isDev ? { execArgv: ['--inspect'], stdio: 'pipe' } : { stdio: 'pipe' },
   );
 
-  serverProcess.stdout.on('data', (chunk: Buffer) => {
+  serverProcess.stdout?.on('data', (chunk: Buffer) => {
     // Send the Server console.log messages to the main browser window
     clientWin?.webContents.executeJavaScript(`
       console.info('Server Log:', ${JSON.stringify(chunk.toString('utf8'))})`);
   });
 
-  serverProcess.stderr.on('data', (chunk: Buffer) => {
+  serverProcess.stderr?.on('data', (chunk: Buffer) => {
     // Send the Server console.error messages out to the main browser window
     clientWin?.webContents.executeJavaScript(`
       console.error('Server Log:', ${JSON.stringify(chunk.toString('utf8'))})`);
@@ -111,6 +108,7 @@ async function createWindow() {
       preload: __dirname + '/preload.js',
     },
   });
+
   win.setBackgroundColor('#E8ECF0');
 
   if (isDev) {
@@ -220,34 +218,49 @@ app.on('ready', async () => {
   // Install an `app://` protocol that always returns the base HTML
   // file no matter what URL it is. This allows us to use react-router
   // on the frontend
-  protocol.registerFileProtocol('app', (request, callback) => {
+  protocol.handle('app', request => {
     if (request.method !== 'GET') {
-      callback({ error: -322 }); // METHOD_NOT_SUPPORTED from chromium/src/net/base/net_error_list.h
-      return null;
+      return new Response(null, {
+        status: 405,
+        statusText: 'Method Not Allowed',
+      });
     }
 
     const parsedUrl = new URL(request.url);
     if (parsedUrl.protocol !== 'app:') {
-      callback({ error: -302 }); // UNKNOWN_URL_SCHEME
-      return;
+      return new Response(null, {
+        status: 404,
+        statusText: 'Unknown URL Scheme',
+      });
     }
 
     if (parsedUrl.host !== 'actual') {
-      callback({ error: -105 }); // NAME_NOT_RESOLVED
-      return;
+      return new Response(null, {
+        status: 404,
+        statusText: 'Host Not Resolved',
+      });
     }
 
     const pathname = parsedUrl.pathname;
 
+    let filePath = path.normalize(`${__dirname}/client-build/index.html`); // default web path
+
     if (pathname.startsWith('/static')) {
-      callback({
-        path: path.normalize(`${__dirname}/client-build${pathname}`),
-      });
-    } else {
-      callback({
-        path: path.normalize(`${__dirname}/client-build/index.html`),
-      });
+      // static assets
+      filePath = path.normalize(`${__dirname}/client-build${pathname}`);
+      const resolvedPath = path.resolve(filePath);
+      const clientBuildPath = path.resolve(__dirname, 'client-build');
+
+      // Ensure filePath is within client-build directory - prevents directory traversal vulnerability
+      if (!resolvedPath.startsWith(clientBuildPath)) {
+        return new Response(null, {
+          status: 403,
+          statusText: 'Forbidden',
+        });
+      }
     }
+
+    return net.fetch(`file:///${filePath}`);
   });
 
   if (process.argv[1] !== '--server') {
@@ -298,8 +311,11 @@ ipcMain.on('get-bootstrap-data', event => {
 });
 
 ipcMain.handle('restart-server', () => {
-  serverProcess.kill();
-  serverProcess = null;
+  if (serverProcess) {
+    serverProcess.kill();
+    serverProcess = null;
+  }
+
   createBackgroundProcess();
 });
 
diff --git a/upcoming-release-notes/3475.md b/upcoming-release-notes/3475.md
new file mode 100644
index 0000000000000000000000000000000000000000..49af54b1cb16e876ceb3dbf0ca53eb840a83e675
--- /dev/null
+++ b/upcoming-release-notes/3475.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [MikesGlitch]
+---
+
+Replacing the deprecated Electron file handler protocol with the new version