mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-16 14:16:16 -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
@@ -103,3 +103,49 @@ Rules:
|
||||
When changing this flow, keep stale header cleanup covered. Switching from a
|
||||
channel or playlist with custom headers to one without custom headers must clear
|
||||
the previous override.
|
||||
|
||||
## Main-Process Remote Requests
|
||||
|
||||
Renderer-triggered HTTP requests must pass through the URL policy in
|
||||
`apps/electron-backend/src/app/events/url-safety.ts`. The policy rejects
|
||||
non-HTTP(S) URLs and embedded credentials, and strict callers also reject
|
||||
loopback, private, reserved, and DNS-resolved private addresses. IPv4-mapped
|
||||
IPv6 literals are decoded before classification, including hexadecimal forms
|
||||
such as `::ffff:7f00:1`, so alternate IPv6 spelling cannot bypass IPv4 rules.
|
||||
|
||||
Remote request callers must use the validated Axios redirect helper so every
|
||||
redirect target is checked before the main process follows it. Under the strict
|
||||
policy, the helper pins the socket lookup to the IP addresses that passed
|
||||
validation while retaining the original hostname for TLS SNI, certificate
|
||||
validation, and virtual hosting. This prevents DNS rebinding between validation
|
||||
and connection. Callers with custom TLS policy provide a typed agent factory;
|
||||
the validated request layer supplies the pinned lookup instead of copying
|
||||
private Node `Agent.options` state. Cross-origin redirects must not forward `Authorization`,
|
||||
`Cookie`, `Proxy-Authorization`, Axios `params`, or request bodies.
|
||||
|
||||
EPG URLs are strict by default because an M3U playlist can supply them through
|
||||
`url-tvg`. Operators who intentionally use a LAN-hosted EPG source can opt in
|
||||
for that run with `IPTVNATOR_ALLOW_PRIVATE_NETWORK_URLS=1`. Directly configured
|
||||
Xtream, Stalker, and playlist providers retain private-network support, but
|
||||
still require HTTP(S), reject embedded credentials, and validate redirects.
|
||||
|
||||
Remote playlist TLS certificates are validated by default. The
|
||||
`IPTVNATOR_ALLOW_INSECURE_TLS=1` escape hatch is only for explicitly trusted
|
||||
providers with invalid or self-signed certificates.
|
||||
|
||||
## Filesystem Capabilities
|
||||
|
||||
Renderer IPC payloads are not filesystem authorization.
|
||||
|
||||
- `write-file` accepts only a path returned to the same renderer by the native
|
||||
save dialog. The capability is single-use and is consumed before the write,
|
||||
including when the filesystem operation fails.
|
||||
- Download folders are owned by the Electron main process. The OS downloads
|
||||
directory is always allowed; a custom directory is accepted only after the
|
||||
native folder dialog selects it.
|
||||
- The selected download directory is persisted under Electron `userData` and
|
||||
returned by `DOWNLOADS_GET_DEFAULT_FOLDER`, so renderer-managed settings
|
||||
cannot substitute an arbitrary host path.
|
||||
- Downloads do not overwrite an existing destination file.
|
||||
- Reveal and playback handlers accept only file paths recorded in IPTVnator's
|
||||
downloads database.
|
||||
Reference in new issue
Block a user