Enable Preload sandboxing

Depends on https://github.com/Vendicated/Vencord/pull/3797
This commit is contained in:
Vendicated
2025-11-24 00:59:41 +01:00
parent 02ab7165aa
commit d0e7bd479a
8 changed files with 61 additions and 67 deletions

View File

@@ -18,17 +18,15 @@ import {
session,
shell
} from "electron";
import { mkdirSync, readFileSync, watch } from "fs";
import { open, readFile } from "fs/promises";
import { readFileSync, watch } from "fs";
import { readFile } from "fs/promises";
import { enableHardwareAcceleration } from "main";
import { release } from "os";
import { join } from "path";
import { debounce } from "shared/utils/debounce";
import { IpcEvents } from "../shared/IpcEvents";
import { setBadgeCount } from "./appBadge";
import { autoStart } from "./autoStart";
import { VENCORD_QUICKCSS_FILE, VENCORD_THEMES_DIR } from "./constants";
import { mainWin } from "./mainWindow";
import { Settings, State } from "./settings";
import { handle, handleSync } from "./utils/ipcWrappers";
@@ -37,13 +35,26 @@ import { isDeckGameMode, showGamePage } from "./utils/steamOS";
import { isValidVencordInstall } from "./utils/vencordLoader";
import { VENCORD_FILES_DIR } from "./vencordFilesDir";
handleSync(IpcEvents.GET_VENCORD_PRELOAD_FILE, () => join(VENCORD_FILES_DIR, "vencordDesktopPreload.js"));
handleSync(IpcEvents.GET_VENCORD_PRELOAD_SCRIPT, () =>
readFileSync(join(VENCORD_FILES_DIR, "vencordDesktopPreload.js"), "utf-8")
);
handleSync(IpcEvents.GET_VENCORD_RENDERER_SCRIPT, () =>
readFileSync(join(VENCORD_FILES_DIR, "vencordDesktopRenderer.js"), "utf-8")
);
handleSync(IpcEvents.GET_RENDERER_SCRIPT, () => readFileSync(join(__dirname, "renderer.js"), "utf-8"));
handleSync(IpcEvents.GET_RENDERER_CSS_FILE, () => join(__dirname, "renderer.css"));
const VESKTOP_RENDERER_JS_PATH = join(__dirname, "renderer.js");
const VESKTOP_RENDERER_CSS_PATH = join(__dirname, "renderer.css");
handleSync(IpcEvents.GET_VESKTOP_RENDERER_SCRIPT, () => readFileSync(VESKTOP_RENDERER_JS_PATH, "utf-8"));
handle(IpcEvents.GET_VESKTOP_RENDERER_CSS, () => readFile(VESKTOP_RENDERER_CSS_PATH, "utf-8"));
if (IS_DEV) {
watch(VESKTOP_RENDERER_CSS_PATH, { persistent: false }, async () => {
mainWin.webContents.postMessage(
IpcEvents.VESKTOP_RENDERER_CSS_UPDATE,
await readFile(VESKTOP_RENDERER_CSS_PATH, "utf-8")
);
});
}
handleSync(IpcEvents.GET_SETTINGS, () => Settings.plain);
handleSync(IpcEvents.GET_VERSION, () => app.getVersion());
@@ -159,27 +170,3 @@ function openDebugPage(page: string) {
handle(IpcEvents.DEBUG_LAUNCH_GPU, () => openDebugPage("chrome://gpu"));
handle(IpcEvents.DEBUG_LAUNCH_WEBRTC_INTERNALS, () => openDebugPage("chrome://webrtc-internals"));
function readCss() {
return readFile(VENCORD_QUICKCSS_FILE, "utf-8").catch(() => "");
}
open(VENCORD_QUICKCSS_FILE, "a+").then(fd => {
fd.close();
watch(
VENCORD_QUICKCSS_FILE,
{ persistent: false },
debounce(async () => {
mainWin?.webContents.postMessage("VencordQuickCssUpdate", await readCss());
}, 50)
);
});
mkdirSync(VENCORD_THEMES_DIR, { recursive: true });
watch(
VENCORD_THEMES_DIR,
{ persistent: false },
debounce(() => {
mainWin?.webContents.postMessage("VencordThemeUpdate", void 0);
})
);

View File

@@ -323,7 +323,7 @@ function buildBrowserWindowOptions(): BrowserWindowConstructorOptions {
backgroundColor,
webPreferences: {
nodeIntegration: false,
sandbox: false, // TODO
sandbox: true,
contextIsolation: true,
devTools: true,
preload: join(__dirname, "preload.js"),

View File

@@ -4,9 +4,9 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { Node } from "@vencord/venmic";
import { ipcRenderer } from "electron";
import { IpcMessage, IpcResponse } from "main/ipcCommands";
import type { Node } from "@vencord/venmic";
import { ipcRenderer } from "electron/renderer";
import type { IpcMessage, IpcResponse } from "main/ipcCommands";
import type { Settings } from "shared/settings";
import { IpcEvents } from "../shared/IpcEvents";

View File

@@ -4,39 +4,44 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { contextBridge, ipcRenderer, webFrame } from "electron";
import { readFileSync, watch } from "fs";
import { contextBridge, ipcRenderer, webFrame } from "electron/renderer";
import { IpcEvents } from "../shared/IpcEvents";
import { invoke } from "./typedIpc";
import { VesktopNative } from "./VesktopNative";
contextBridge.exposeInMainWorld("VesktopNative", VesktopNative);
require(ipcRenderer.sendSync(IpcEvents.GET_VENCORD_PRELOAD_FILE));
// While sandboxed, Electron "polyfills" these APIs as local variables.
// We have to pass them as arguments as they are not global
Function(
"require",
"Buffer",
"process",
"clearImmediate",
"setImmediate",
ipcRenderer.sendSync(IpcEvents.GET_VENCORD_PRELOAD_SCRIPT)
)(require, Buffer, process, clearImmediate, setImmediate);
webFrame.executeJavaScript(ipcRenderer.sendSync(IpcEvents.GET_VENCORD_RENDERER_SCRIPT));
webFrame.executeJavaScript(ipcRenderer.sendSync(IpcEvents.GET_RENDERER_SCRIPT));
webFrame.executeJavaScript(ipcRenderer.sendSync(IpcEvents.GET_VESKTOP_RENDERER_SCRIPT));
// #region css
const rendererCss = ipcRenderer.sendSync(IpcEvents.GET_RENDERER_CSS_FILE);
invoke<string>(IpcEvents.GET_VESKTOP_RENDERER_CSS).then(css => {
const style = document.createElement("style");
style.id = "vcd-css-core";
style.textContent = css;
const style = document.createElement("style");
style.id = "vcd-css-core";
style.textContent = readFileSync(rendererCss, "utf-8");
if (document.readyState === "complete") {
document.documentElement.appendChild(style);
} else {
document.addEventListener("DOMContentLoaded", () => document.documentElement.appendChild(style), {
once: true
});
}
if (document.readyState === "complete") {
document.documentElement.appendChild(style);
} else {
document.addEventListener("DOMContentLoaded", () => document.documentElement.appendChild(style), {
once: true
});
}
if (IS_DEV) {
// persistent means keep process running if watcher is the only thing still running
// which we obviously don't want
watch(rendererCss, { persistent: false }, () => {
document.getElementById("vcd-css-core")!.textContent = readFileSync(rendererCss, "utf-8");
});
}
// #endregion
if (IS_DEV) {
ipcRenderer.on(IpcEvents.VESKTOP_RENDERER_CSS_UPDATE, (e, newCss: string) => {
style.textContent = newCss;
});
}
});

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { contextBridge, ipcRenderer } from "electron";
import { contextBridge, ipcRenderer } from "electron/renderer";
contextBridge.exposeInMainWorld("VesktopSplashNative", {
onUpdateMessage(callback: (message: string) => void) {

View File

@@ -4,8 +4,8 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { ipcRenderer } from "electron";
import { IpcEvents, UpdaterIpcEvents } from "shared/IpcEvents";
import { ipcRenderer } from "electron/renderer";
import type { IpcEvents, UpdaterIpcEvents } from "shared/IpcEvents";
export function invoke<T = any>(event: IpcEvents | UpdaterIpcEvents, ...args: any[]) {
return ipcRenderer.invoke(event, ...args) as Promise<T>;

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { contextBridge, ipcRenderer } from "electron";
import { contextBridge, ipcRenderer } from "electron/renderer";
import type { UpdateInfo } from "electron-updater";
import { UpdaterIpcEvents } from "shared/IpcEvents";

View File

@@ -5,10 +5,12 @@
*/
export const enum IpcEvents {
GET_VENCORD_PRELOAD_FILE = "VCD_GET_VC_PRELOAD_FILE",
GET_VENCORD_PRELOAD_SCRIPT = "VCD_GET_VC_PRELOAD_SCRIPT",
GET_VENCORD_RENDERER_SCRIPT = "VCD_GET_VC_RENDERER_SCRIPT",
GET_RENDERER_SCRIPT = "VCD_GET_RENDERER_SCRIPT",
GET_RENDERER_CSS_FILE = "VCD_GET_RENDERER_CSS_FILE",
GET_VESKTOP_RENDERER_SCRIPT = "VCD_GET_RENDERER_SCRIPT",
GET_VESKTOP_RENDERER_CSS = "VCD_GET_RENDERER_CSS",
VESKTOP_RENDERER_CSS_UPDATE = "VCD_PRELOAD_RENDERER_CSS_UPDATE",
GET_VERSION = "VCD_GET_VERSION",
SUPPORTS_WINDOWS_TRANSPARENCY = "VCD_SUPPORTS_WINDOWS_TRANSPARENCY",