diff --git a/CHANGELOG.md b/CHANGELOG.md index 25b44ef872..1e130bf0a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ - minor improvements to "add second device" dialog #3748 - Remove deprecated translations #3756 - Refactor chat store into React context #3725 -- Improve security: restrict file protocol #3769 #3798 +- Improve security: restrict file protocol #3769 #3798 #3800 - Update `deltachat-node` and `deltachat/jsonrpc-client` to `v1.137.3` - Change chatlist to use new chatlist changed event from core #3268 - Refactor QR code reader #3762 diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 13f1642db2..26bc9bb601 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -118,11 +118,13 @@ export async function init(cwd: string, logHandler: LogHandler) { ev.returnValue = app.getPath(arg) }) - ipcMain.handle('fileChooser', (_ev, options) => { + ipcMain.handle('fileChooser', async (_ev, options) => { if (!mainWindow.window) { throw new Error('window does not exist, this should never happen') } - return dialog.showOpenDialog(mainWindow.window, options) + const returnValue = await dialog.showOpenDialog(mainWindow.window, options) + mainWindow.window.filePathWhiteList.push(...returnValue.filePaths) + return returnValue }) let lastSaveDialogLocation: string | undefined = undefined diff --git a/src/main/windows/main.ts b/src/main/windows/main.ts index 9b4b42e675..f8ba502a44 100644 --- a/src/main/windows/main.ts +++ b/src/main/windows/main.ts @@ -26,7 +26,16 @@ import { fileURLToPath } from 'url' const log = getLogger('main/mainWindow') -export let window: (BrowserWindow & { hidden?: boolean }) | null = null +type ExtendedBrowserWindow = BrowserWindow & { + hidden?: boolean + /** + * whitelist of file paths that user selected that the UI should be able to also load via the file:/// scheme + * example: when changing avatar, we need to display the selected image before it is uploaded to core + */ + filePathWhiteList: string[] +} + +export let window: ExtendedBrowserWindow | null = null export function init(options: { hidden: boolean }) { if (window) { @@ -41,7 +50,7 @@ export function init(options: { hidden: boolean }) { const isMac = platform() === 'darwin' - const main_window = (window = ( + const main_window = (window = ( new electron.BrowserWindow({ backgroundColor: '#282828', // backgroundThrottling: false, // do not throttle animations/timers when page is background @@ -67,6 +76,7 @@ export function init(options: { hidden: boolean }) { titleBarOverlay: true, }) )) + main_window.filePathWhiteList = [] // disable network request to fetch dictionary // issue: https://github.com/electron/electron/issues/22995 @@ -201,6 +211,10 @@ export function init(options: { hidden: boolean }) { return callback({ cancel: false }) } + if (window?.filePathWhiteList.includes(pathname)) { + return callback({ cancel: false }) + } + log.errorWithoutStackTrace( 'tried to access path that is not whitelisted', pathname