Add scoped EPG security trust controls

This commit is contained in:
4gray committed 2026-06-12 15:46:20 +02:00
1 parent 2c032cd3c8
commit 9fd83cc689
35 files changed
+1389 -221

No files matched your search

@@ -67,6 +67,14 @@ export const ELECTRON_BRIDGE_EPG_PROGRESS_STATUSES = {
export type ElectronBridgeEpgProgressStatus =
(typeof ELECTRON_BRIDGE_EPG_PROGRESS_STATUSES)[keyof typeof ELECTRON_BRIDGE_EPG_PROGRESS_STATUSES];
export const ELECTRON_BRIDGE_SECURITY_ERROR_CODES = {
EpgPrivateNetworkBlocked: 'epg-private-network-blocked',
InvalidTlsCertificate: 'invalid-tls-certificate',
} as const;
export type ElectronBridgeSecurityErrorCode =
(typeof ELECTRON_BRIDGE_SECURITY_ERROR_CODES)[keyof typeof ELECTRON_BRIDGE_SECURITY_ERROR_CODES];
export const ELECTRON_BRIDGE_DB_OPERATION_STATUSES = {
Cancelled: 'cancelled',
Completed: 'completed',
@@ -182,6 +190,11 @@ export interface ElectronBridgeEpgFetchResult extends ElectronBridgeResult {
skipped?: string[];
}
export interface ElectronBridgeTrustOptions {
trustedPrivateNetworkEpgUrls?: string[];
trustedInsecureTlsHosts?: string[];
}
export interface ElectronBridgeEpgFreshnessResult {
staleUrls: string[];
freshUrls: string[];
@@ -197,6 +210,8 @@ export interface ElectronBridgeEpgProgress {
status: ElectronBridgeEpgProgressStatus;
stats?: ElectronBridgeEpgProgressStats;
error?: string;
errorCode?: ElectronBridgeSecurityErrorCode;
errorHost?: string;
queuePosition?: number;
}
@@ -437,7 +452,11 @@ export interface ElectronBridgeApi {
onWindowStateChange: (
callback: (state: ElectronBridgeWindowState) => void
) => () => void;
fetchPlaylistByUrl: (url: string, title?: string) => Promise<Playlist>;
fetchPlaylistByUrl: (
url: string,
title?: string,
options?: ElectronBridgeTrustOptions
) => Promise<Playlist>;
updatePlaylistFromFilePath: (
filePath: string,
title: string
@@ -479,8 +498,14 @@ export interface ElectronBridgeApi {
startTime?: number,
headers?: Record<string, string>
) => Promise<ExternalPlayerSession>;
autoUpdatePlaylists: (playlists: Playlist[]) => Promise<Playlist[]>;
fetchEpg: (urls: string[]) => Promise<ElectronBridgeEpgFetchResult>;
autoUpdatePlaylists: (
playlists: Playlist[],
options?: ElectronBridgeTrustOptions
) => Promise<Playlist[]>;
fetchEpg: (
urls: string[],
options?: ElectronBridgeTrustOptions
) => Promise<ElectronBridgeEpgFetchResult>;
getChannelPrograms: (channelId: string) => Promise<EpgProgram[]>;
getCurrentProgramsBatch: (
channelIds: string[]
@@ -493,7 +518,10 @@ export interface ElectronBridgeApi {
skip: number,
limit: number
) => Promise<ElectronBridgeEpgChannelWithPrograms[]>;
forceFetchEpg: (url: string) => Promise<ElectronBridgeEpgFetchResult>;
forceFetchEpg: (
url: string,
options?: ElectronBridgeTrustOptions
) => Promise<ElectronBridgeEpgFetchResult>;
clearEpgData: () => Promise<ElectronBridgeResult>;
checkEpgFreshness: (
urls: string[],
@@ -25,4 +25,5 @@ export interface PlaylistRefreshPayload {
title: string;
filePath?: string;
url?: string;
trustedInsecureTlsHosts?: string[];
}
@@ -66,4 +66,16 @@ export interface Settings {
* Only meaningful for Xtream playlists in Electron.
*/
preferUploadedEpgOverXtream?: boolean;
/**
* Exact EPG source URLs the user has allowed to resolve to private/LAN
* network addresses. Kept source-scoped instead of disabling SSRF
* protection globally.
*/
trustedPrivateNetworkEpgUrls?: string[];
/**
* Lowercase hostnames whose invalid TLS certificates the user has chosen
* to trust. This is host-scoped and does not disable TLS validation for
* unrelated playlist or EPG hosts.
*/
trustedInsecureTlsHosts?: string[];
}