From b9e9d9bd64ae5873e4406e2c4093fb9772b61783 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Fri, 2 Dec 2022 14:10:40 +0100 Subject: [PATCH] Add --vanilla flag, strip csp on mainFrame only --- src/patcher.ts | 174 +++++++++++++++++++++++++------------------------ 1 file changed, 89 insertions(+), 85 deletions(-) diff --git a/src/patcher.ts b/src/patcher.ts index 12cefc01..0849e5a8 100644 --- a/src/patcher.ts +++ b/src/patcher.ts @@ -42,98 +42,102 @@ require.main!.filename = join(asarPath, discordPkg.main); // @ts-ignore Untyped method? Dies from cringe app.setAppPath(asarPath); -// Repatch after host updates on Windows -if (process.platform === "win32") - require("./patchWin32Updater"); - -class BrowserWindow extends electron.BrowserWindow { - constructor(options: BrowserWindowConstructorOptions) { - if (options?.webPreferences?.preload && options.title) { - const original = options.webPreferences.preload; - options.webPreferences.preload = join(__dirname, "preload.js"); - options.webPreferences.sandbox = false; - - process.env.DISCORD_PRELOAD = original; - - super(options); - initIpc(this); - } else super(options); - } -} -Object.assign(BrowserWindow, electron.BrowserWindow); -// esbuild may rename our BrowserWindow, which leads to it being excluded -// from getFocusedWindow(), so this is necessary -// https://github.com/discord/electron/blob/13-x-y/lib/browser/api/browser-window.ts#L60-L62 -Object.defineProperty(BrowserWindow, "name", { value: "BrowserWindow", configurable: true }); - -// Replace electrons exports with our custom BrowserWindow -const electronPath = require.resolve("electron"); -delete require.cache[electronPath]!.exports; -require.cache[electronPath]!.exports = { - ...electron, - BrowserWindow -}; - -// Patch appSettings to force enable devtools -onceDefined(global, "appSettings", s => - s.set("DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING", true) -); - -process.env.DATA_DIR = join(app.getPath("userData"), "..", "Vencord"); - -electron.app.whenReady().then(() => { - // Source Maps! Maybe there's a better way but since the renderer is executed - // from a string I don't think any other form of sourcemaps would work - electron.protocol.registerFileProtocol("vencord", ({ url: unsafeUrl }, cb) => { - let url = unsafeUrl.slice("vencord://".length); - if (url.endsWith("/")) url = url.slice(0, -1); - switch (url) { - case "renderer.js.map": - case "preload.js.map": - case "patcher.js.map": // doubt - cb(join(__dirname, url)); - break; - default: - cb({ statusCode: 403 }); +if (!process.argv.includes("--vanilla")) { + // Repatch after host updates on Windows + if (process.platform === "win32") + require("./patchWin32Updater"); + + class BrowserWindow extends electron.BrowserWindow { + constructor(options: BrowserWindowConstructorOptions) { + if (options?.webPreferences?.preload && options.title) { + const original = options.webPreferences.preload; + options.webPreferences.preload = join(__dirname, "preload.js"); + options.webPreferences.sandbox = false; + + process.env.DISCORD_PRELOAD = original; + + super(options); + initIpc(this); + } else super(options); } - }); + } + Object.assign(BrowserWindow, electron.BrowserWindow); + // esbuild may rename our BrowserWindow, which leads to it being excluded + // from getFocusedWindow(), so this is necessary + // https://github.com/discord/electron/blob/13-x-y/lib/browser/api/browser-window.ts#L60-L62 + Object.defineProperty(BrowserWindow, "name", { value: "BrowserWindow", configurable: true }); + + // Replace electrons exports with our custom BrowserWindow + const electronPath = require.resolve("electron"); + delete require.cache[electronPath]!.exports; + require.cache[electronPath]!.exports = { + ...electron, + BrowserWindow + }; - try { - const settings = JSON.parse(readSettings()); - if (settings.enableReactDevtools) - installExt("fmkadmapgofadopljbjfkapdkoienihi") - .then(() => console.info("[Vencord] Installed React Developer Tools")) - .catch(err => console.error("[Vencord] Failed to install React Developer Tools", err)); - } catch { } - - - // Remove CSP - function patchCsp(headers: Record, header: string) { - if (header in headers) { - let patchedHeader = headers[header][0]; - for (const directive of ["style-src", "connect-src", "img-src", "font-src", "media-src"]) { - patchedHeader = patchedHeader.replace(new RegExp(`${directive}.+?;`), `${directive} * blob: data: 'unsafe-inline';`); + // Patch appSettings to force enable devtools + onceDefined(global, "appSettings", s => + s.set("DANGEROUS_ENABLE_DEVTOOLS_ONLY_ENABLE_IF_YOU_KNOW_WHAT_YOURE_DOING", true) + ); + + process.env.DATA_DIR = join(app.getPath("userData"), "..", "Vencord"); + + electron.app.whenReady().then(() => { + // Source Maps! Maybe there's a better way but since the renderer is executed + // from a string I don't think any other form of sourcemaps would work + electron.protocol.registerFileProtocol("vencord", ({ url: unsafeUrl }, cb) => { + let url = unsafeUrl.slice("vencord://".length); + if (url.endsWith("/")) url = url.slice(0, -1); + switch (url) { + case "renderer.js.map": + case "preload.js.map": + case "patcher.js.map": // doubt + cb(join(__dirname, url)); + break; + default: + cb({ statusCode: 403 }); + } + }); + + try { + const settings = JSON.parse(readSettings()); + if (settings.enableReactDevtools) + installExt("fmkadmapgofadopljbjfkapdkoienihi") + .then(() => console.info("[Vencord] Installed React Developer Tools")) + .catch(err => console.error("[Vencord] Failed to install React Developer Tools", err)); + } catch { } + + + // Remove CSP + function patchCsp(headers: Record, header: string) { + if (header in headers) { + let patchedHeader = headers[header][0]; + for (const directive of ["style-src", "connect-src", "img-src", "font-src", "media-src"]) { + patchedHeader = patchedHeader.replace(new RegExp(`${directive}.+?;`), `${directive} * blob: data: 'unsafe-inline';`); + } + // TODO: Restrict this to only imported packages with fixed version. + // Perhaps auto generate with esbuild + patchedHeader = patchedHeader.replace(/script-src.+?(?=;)/, "$& 'unsafe-eval' https://unpkg.com https://cdnjs.cloudflare.com"); + headers[header] = [patchedHeader]; } - // TODO: Restrict this to only imported packages with fixed version. - // Perhaps auto generate with esbuild - patchedHeader = patchedHeader.replace(/script-src.+?(?=;)/, "$& 'unsafe-eval' https://unpkg.com https://cdnjs.cloudflare.com"); - headers[header] = [patchedHeader]; } - } - electron.session.defaultSession.webRequest.onHeadersReceived(({ responseHeaders, url }, cb) => { - if (responseHeaders) { - patchCsp(responseHeaders, "content-security-policy"); - patchCsp(responseHeaders, "content-security-policy-report-only"); + electron.session.defaultSession.webRequest.onHeadersReceived(({ responseHeaders, resourceType }, cb) => { + if (responseHeaders) { + if (resourceType === "mainFrame") + patchCsp(responseHeaders, "content-security-policy"); - // Fix hosts that don't properly set the content type, such as - // raw.githubusercontent.com - if (url.endsWith(".css")) - responseHeaders["content-type"] = ["text/css"]; - } - cb({ cancel: false, responseHeaders }); + // Fix hosts that don't properly set the css content type, such as + // raw.githubusercontent.com + if (resourceType === "stylesheet") + responseHeaders["content-type"] = ["text/css"]; + } + cb({ cancel: false, responseHeaders }); + }); }); -}); +} else { + console.log("[Vencord] Running in vanilla mode. Not loading Vencord"); +} console.log("[Vencord] Loading original Discord app.asar"); // Legacy Vencord Injector requires "../app.asar". However, because we