From bb29be8e335d67c496dbf93166b1055804832097 Mon Sep 17 00:00:00 2001 From: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Date: Mon, 16 Oct 2023 21:06:48 -0700 Subject: [PATCH] restrict content types --- src/main/main.ts | 26 +++++++++++++-- src/main/preload/local-settings.ts | 7 +++- .../general/application-settings.tsx | 32 ++++++++++++++++++- 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/main/main.ts b/src/main/main.ts index 562fff49a..0409a21fd 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -657,10 +657,32 @@ app.on('window-all-closed', () => { } }); +const FONT_HEADERS = [ + 'font/collection', + 'font/otf', + 'font/sfnt', + 'font/ttf', + 'font/woff', + 'font/woff2', +]; + app.whenReady() .then(() => { - protocol.handle('feishin', (request) => { - return net.fetch(`file://${request.url.slice('feishin://'.length)}`); + protocol.handle('feishin', async (request) => { + const filePath = `file://${request.url.slice('feishin://'.length)}`; + const response = await net.fetch(filePath); + const contentType = response.headers.get('content-type'); + + if (!contentType || !FONT_HEADERS.includes(contentType)) { + getMainWindow()?.webContents.send('custom-font-error', filePath); + + return new Response(null, { + status: 403, + statusText: 'Forbidden', + }); + } + + return response; }); createWindow(); diff --git a/src/main/preload/local-settings.ts b/src/main/preload/local-settings.ts index ee8044e0b..a57b08c4f 100644 --- a/src/main/preload/local-settings.ts +++ b/src/main/preload/local-settings.ts @@ -1,4 +1,4 @@ -import { ipcRenderer, webFrame } from 'electron'; +import { IpcRendererEvent, ipcRenderer, webFrame } from 'electron'; import Store from 'electron-store'; const store = new Store(); @@ -39,9 +39,14 @@ const setZoomFactor = (zoomFactor: number) => { webFrame.setZoomFactor(zoomFactor / 100); }; +const fontError = (cb: (event: IpcRendererEvent, file: string) => void) => { + ipcRenderer.on('custom-font-error', cb); +}; + export const localSettings = { disableMediaKeys, enableMediaKeys, + fontError, get, passwordGet, passwordRemove, diff --git a/src/renderer/features/settings/components/general/application-settings.tsx b/src/renderer/features/settings/components/general/application-settings.tsx index 0423b1e67..061f6b006 100644 --- a/src/renderer/features/settings/components/general/application-settings.tsx +++ b/src/renderer/features/settings/components/general/application-settings.tsx @@ -1,3 +1,4 @@ +import type { IpcRendererEvent } from 'electron'; import isElectron from 'is-electron'; import { FileInput, NumberInput, Select, toast } from '/@/renderer/components'; import { @@ -9,10 +10,11 @@ import { useGeneralSettings, useSettingsStoreActions, } from '/@/renderer/store/settings.store'; -import { useEffect, useMemo, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { FontType } from '/@/renderer/types'; const localSettings = isElectron() ? window.electron.localSettings : null; +const ipc = isElectron() ? window.electron.ipc : null; type Font = { label: string; @@ -56,6 +58,34 @@ export const ApplicationSettings = () => { return null; }, [fontSettings.custom]); + const onFontError = useCallback( + (_: IpcRendererEvent, file: string) => { + toast.error({ + message: `${file} is not a valid font file`, + }); + + setSettings({ + font: { + ...fontSettings, + custom: null, + }, + }); + }, + [fontSettings, setSettings], + ); + + useEffect(() => { + if (localSettings) { + localSettings.fontError(onFontError); + + return () => { + ipc!.removeAllListeners('custom-font-error'); + }; + } + + return () => {}; + }, [onFontError]); + useEffect(() => { const getFonts = async () => { if (