mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-15 05:36:17 -08:00
fix(security): complete Electron hardening and review follow-ups
* fix(security): harden Electron IPC against MITM, SSRF, path and injection risks S1 TLS: validate certs by default on playlist/EPG fetches (opt-out via IPTVNATOR_ALLOW_INSECURE_TLS); new util/secure-https.ts. S2: write-file IPC restricted to save-dialog-authorized paths. S3: XTREAM_PROBE_URL guarded by assertRemoteUrlAllowed + maxRedirects:0; new events/url-safety.ts (+19 tests). S4: EPG titles rendered via interpolation, not [innerHTML]. S5: downloads reveal/play limited to recorded download paths. S6: Stalker cmd encoded (slash-preserving) to block query injection. EPG-worker and Stalker fetches reject file://-style/credentialed URLs; LAN/self-hosted targets remain allowed. * perf(player): lazy-load web video players via @defer Wrap Video.js/HTML5/ArtPlayer in @defer (on immediate) so video.js, hls.js, artplayer and mpegts.js split into a deferred chunk loaded on first playback instead of eagerly on the player route. Embedded MPV (native) stays eager. Spec uses DeferBlockBehavior.Playthrough. * fix(player): remove leaked HTML video listeners on destroy volumechange used a mismatched removeEventListener reference, while loadedmetadata and timeupdate were never removed at all. Bind all three to stable handler fields used for both add and remove, and add a teardown regression test asserting each listener is detached on destroy. * refactor(dashboard): extract pure navigation helpers from DashboardDataService Move the 8 stateless link/navigation-state/type-kind helpers into a new dashboard-navigation.util.ts so the routing logic is independently testable and the 1260-line god-service shrinks. DashboardDataService keeps the public methods as thin delegators (facade) so the public API and the single consumer (workspace-dashboard-rails) are unchanged. First slice of the DashboardDataService decomposition; verified by the existing service spec (33/33) and the app typecheck. * fix(review): address PR feedback (IPv6 link-local, write-path cap, @defer placeholder) - url-safety: broaden IPv6 link-local detection to the full fe80::/10 range (fe80:: through febf::), not just the fe80:: prefix (+ regression tests). - playlist.events: cap authorizedWritePaths (evict oldest past 32) so a save dialog opened without a following write cannot accumulate entries until restart. - web-player-view: add a @placeholder to each @defer (on immediate) player block to avoid the one-frame blank/layout-shift before the chunk resolves. * fix(security): close Electron network and download gaps * test(downloads): cover cancellation and restart cleanup * fix(downloads): address Greptile review gaps * test(security): reproduce remaining Greptile findings * fix(security): close remaining Greptile findings * test(downloads): reproduce early database queue stall * fix(downloads): release queue after setup failures * test(downloads): reproduce completion queue stall * fix(downloads): release queue after completion failures
This commit is contained in:
1 parent
7775553a6b
commit
2c032cd3c8
44 files changed
+3646
-1124
No files matched your search
@@ -0,0 +1,36 @@
|
||||
import { Agent } from 'node:https';
|
||||
import type { LookupFunction } from 'node:net';
|
||||
import type { ValidatedRequestAgentFactory } from './validated-axios';
|
||||
|
||||
const INSECURE_TLS_ENV = 'IPTVNATOR_ALLOW_INSECURE_TLS';
|
||||
|
||||
/**
|
||||
* Whether TLS certificate validation is disabled for remote playlist fetches.
|
||||
*
|
||||
* Secure by default. Validation is only disabled when the operator explicitly
|
||||
* opts in via `IPTVNATOR_ALLOW_INSECURE_TLS=1` (or `=true`). Some IPTV
|
||||
* providers serve self-signed or otherwise invalid certificates, so the
|
||||
* opt-out exists — but it must never be the default, otherwise every playlist
|
||||
* fetch is silently exposed to network MITM.
|
||||
*/
|
||||
export function isInsecureTlsAllowed(): boolean {
|
||||
const value = process.env[INSECURE_TLS_ENV]?.trim().toLowerCase();
|
||||
return value === '1' || value === 'true';
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the agent factory used for remote playlist fetches.
|
||||
*
|
||||
* Certificates are validated unless insecure TLS has been explicitly opted in
|
||||
* (see {@link isInsecureTlsAllowed}). The validated request layer supplies a
|
||||
* DNS lookup pinned to the addresses approved for each redirect hop.
|
||||
*/
|
||||
export function createPlaylistAgentFactory(): ValidatedRequestAgentFactory & {
|
||||
createHttpsAgent(lookup?: LookupFunction): Agent;
|
||||
} {
|
||||
const rejectUnauthorized = !isInsecureTlsAllowed();
|
||||
|
||||
return {
|
||||
createHttpsAgent: (lookup) => new Agent({ lookup, rejectUnauthorized }),
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user