Harden app updater: per-hop redirect pinning, truncation + path-guard fixes
Review follow-ups on the in-app updater: - Download via Electron net.request with redirect:'manual', re-validating the host on EVERY hop. fetch() followed redirects automatically and undici hides the Location header, so the trusted-host pin only covered the first URL — a 302 from the trusted host could bounce the download to an arbitrary server. - Reject truncated downloads (received !== Content-Length) and an 'aborted' mid-stream so a partial installer is never launched; clean up the temp file on any failure. - runAppUpdate: compare the parent dir by equality instead of startsWith(), which a sibling like `<temp>_evil\x.exe` defeated. - checkForAppUpdate: 15s AbortController timeout (mirrors the yt-dlp calls) and pin htmlUrl to the trusted host before handing it to the OS browser. - parseVersion: ignore -prerelease/+build suffixes so a prerelease never sorts above its final release. - SettingsView: funnel a failed check into the single error slot so two error messages can't render at once. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -256,7 +256,11 @@ export function SettingsView(): React.JSX.Element {
|
||||
setAppUpd(null)
|
||||
setAppUpdError(null)
|
||||
try {
|
||||
setAppUpd(await window.api.checkForAppUpdate())
|
||||
const info = await window.api.checkForAppUpdate()
|
||||
// Funnel a failed check into the single error slot rather than storing a
|
||||
// second not-ok AppUpdateInfo, so only one error message can ever render.
|
||||
if (info.ok) setAppUpd(info)
|
||||
else setAppUpdError(info.error ?? 'Update check failed.')
|
||||
} catch (e) {
|
||||
setAppUpdError(e instanceof Error ? e.message : String(e))
|
||||
} finally {
|
||||
@@ -883,11 +887,6 @@ export function SettingsView(): React.JSX.Element {
|
||||
<Text>You're up to date — v{appUpd.currentVersion} is the latest.</Text>
|
||||
)}
|
||||
|
||||
{appUpd && !appUpd.ok && (
|
||||
<Caption1 style={{ color: tokens.colorPaletteRedForeground1, whiteSpace: 'pre-wrap' }}>
|
||||
{appUpd.error}
|
||||
</Caption1>
|
||||
)}
|
||||
{appUpdError && (
|
||||
<Caption1 style={{ color: tokens.colorPaletteRedForeground1, whiteSpace: 'pre-wrap' }}>
|
||||
{appUpdError}
|
||||
|
||||
Reference in New Issue
Block a user