Apply additional security recommendations (#2050)

* enable sandbox

* enable CSP (umami tentatively works?) and reduce amount of ipc APIs exposed

* remove csp from index
This commit is contained in:
Kendall Garner
2026-05-23 05:09:22 +00:00
committed by GitHub
parent 0de1e1aa3e
commit 7befd70e21
19 changed files with 179 additions and 190 deletions
@@ -112,7 +112,7 @@ export const useMainPlayerListener = () => {
decreaseVolume(volumeWheelStep);
});
mpvPlayerListener.rendererError((_event: any, message: string) => {
mpvPlayerListener.rendererError((message: string) => {
handleMpvError(message);
});
@@ -117,11 +117,11 @@ export const useMPRIS = () => {
return;
}
mpris?.requestPosition((_e: unknown, data: { position: number }) => {
mpris?.requestPosition((data: { position: number }) => {
player.mediaSeekToTimestamp(data.position);
});
mpris?.requestSeek((_e: unknown, data: { offset: number }) => {
mpris?.requestSeek((data: { offset: number }) => {
player.mediaSkipForward(data.offset);
});
@@ -133,7 +133,7 @@ export const useMPRIS = () => {
player.toggleShuffle();
});
mpris?.requestVolume((_e: unknown, data: { volume: number }) => {
mpris?.requestVolume((data: { volume: number }) => {
player.setVolume(data.volume);
});
@@ -4,27 +4,27 @@ import React, { useCallback, useEffect } from 'react';
import { usePlayerStatus, useSettingsStore, useWindowSettings } from '/@/renderer/store';
import { PlayerStatus } from '/@/shared/types/types';
const ipc = isElectron() ? window.api.ipc : null;
const utils = isElectron() ? window.api.utils : null;
export const usePowerSaveBlocker = () => {
const status = usePlayerStatus();
const { preventSleepOnPlayback, preventSuspendOnPlayback } = useWindowSettings();
const startPowerSaveBlocker = useCallback(async () => {
if (!ipc) return;
if (!utils) return;
try {
await ipc.invoke('power-save-blocker-start', { full: preventSleepOnPlayback });
await utils.startPowerSaveBlocker(preventSleepOnPlayback);
} catch (error) {
console.error('Failed to start power save blocker:', error);
}
}, [preventSleepOnPlayback]);
const stopPowerSaveBlocker = useCallback(async () => {
if (!ipc) return;
if (!utils) return;
try {
await ipc.invoke('power-save-blocker-stop');
await utils.stopPowerSaveBlocker();
} catch (error) {
console.error('Failed to stop power save blocker:', error);
}
@@ -64,7 +64,7 @@ export const useRemote = () => {
return;
}
remote.requestPosition((_e: unknown, data: { position: number }) => {
remote.requestPosition((data: { position: number }) => {
logFn.debug(logMsg[LogCategory.REMOTE].requestPositionReceived, {
category: LogCategory.REMOTE,
meta: { position: data.position },
@@ -73,7 +73,7 @@ export const useRemote = () => {
player.mediaSeekToTimestamp(newTime);
});
remote.requestSeek((_e: unknown, data: { offset: number }) => {
remote.requestSeek((data: { offset: number }) => {
logFn.debug(logMsg[LogCategory.REMOTE].requestSeekReceived, {
category: LogCategory.REMOTE,
meta: { offset: data.offset },
@@ -81,17 +81,15 @@ export const useRemote = () => {
mediaSkipForward(data.offset);
});
remote.requestRating(
(_e: unknown, data: { id: string; rating: number; serverId: string }) => {
logFn.debug(logMsg[LogCategory.REMOTE].requestRatingReceived, {
category: LogCategory.REMOTE,
meta: { id: data.id, rating: data.rating, serverId: data.serverId },
});
setRating(data.serverId, [data.id], LibraryItem.SONG, data.rating);
},
);
remote.requestRating((data: { id: string; rating: number; serverId: string }) => {
logFn.debug(logMsg[LogCategory.REMOTE].requestRatingReceived, {
category: LogCategory.REMOTE,
meta: { id: data.id, rating: data.rating, serverId: data.serverId },
});
setRating(data.serverId, [data.id], LibraryItem.SONG, data.rating);
});
remote.requestVolume((_e: unknown, data: { volume: number }) => {
remote.requestVolume((data: { volume: number }) => {
logFn.debug(logMsg[LogCategory.REMOTE].requestVolumeReceived, {
category: LogCategory.REMOTE,
meta: { volume: data.volume },
@@ -99,24 +97,20 @@ export const useRemote = () => {
setVolume(data.volume);
});
remote.requestFavorite(
(_e: unknown, data: { favorite: boolean; id: string; serverId: string }) => {
logFn.debug(logMsg[LogCategory.REMOTE].requestFavoriteReceived, {
category: LogCategory.REMOTE,
meta: { favorite: data.favorite, id: data.id, serverId: data.serverId },
});
const mutator = data.favorite
? addToFavoritesMutation
: removeFromFavoritesMutation;
mutator.mutate({
apiClientProps: { serverId: data.serverId },
query: {
id: [data.id],
type: LibraryItem.SONG,
},
});
},
);
remote.requestFavorite((data: { favorite: boolean; id: string; serverId: string }) => {
logFn.debug(logMsg[LogCategory.REMOTE].requestFavoriteReceived, {
category: LogCategory.REMOTE,
meta: { favorite: data.favorite, id: data.id, serverId: data.serverId },
});
const mutator = data.favorite ? addToFavoritesMutation : removeFromFavoritesMutation;
mutator.mutate({
apiClientProps: { serverId: data.serverId },
query: {
id: [data.id],
type: LibraryItem.SONG,
},
});
});
return () => {
ipc?.removeAllListeners('request-position');
@@ -1,5 +1,3 @@
import type { IpcRendererEvent } from 'electron';
import { t } from 'i18next';
import isElectron from 'is-electron';
import { memo, useCallback, useEffect, useState } from 'react';
@@ -124,7 +122,7 @@ export const ApplicationSettings = memo(() => {
// }, [fontSettings.custom]);
const onFontError = useCallback(
(_: IpcRendererEvent, file: string) => {
(file: string) => {
toast.error({
message: `${file} is not a valid font file`,
});
-1
View File
@@ -2,7 +2,6 @@
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<title>Feishin</title>
<% if (web) { %>
+2 -2
View File
@@ -21,14 +21,14 @@ export const UpdateAvailableDialog = () => {
useEffect(() => {
if (!isElectron()) return;
const handleUpdateAvailable = (_event: any, newVersion: string) => {
const handleUpdateAvailable = (newVersion: string) => {
if (versionDismissed !== newVersion) {
setVersion(newVersion);
setOpened(true);
}
};
window.api.ipc.on('update-available', handleUpdateAvailable);
window.api.utils.rendererUpdateAvailable(handleUpdateAvailable);
return () => {
window.api.ipc.removeListener?.('update-available', handleUpdateAvailable);