mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-08-07 19:21:32 -07:00
fix(anime): harden the extension bridge against untrusted repos and hangs
Addresses CodeRabbit review feedback on the Anime Browser: - reject repository package/apk names that are not plain identifiers, and verify the install target resolves inside the extensions directory - count mpv's %n% option escape in UTF-8 bytes, and escape backslashes in header values so a trailing one cannot eat the list separator - key the bridge extension-id cache by APK content, so an in-place upgrade re-uploads instead of running the previous build - bound every bridge, release-listing, and download request with a timeout - enforce the APK size limit while streaming rather than after buffering - read APK bytes on demand instead of holding a base64 copy per extension for the lifetime of the browser - serialize preference mutations and write the file atomically - handle the sidecar spawn error event, and wait for the child to exit in stop() before returning - report a failed Anime Browser bootstrap instead of showing the starting banner forever - keep the preferences panel's save confirmation and in-flight multi-select edits by re-rendering only on a structural schema change
This commit is contained in:
@@ -17,6 +17,10 @@ import {
|
||||
|
||||
export type InstallStage = 'locating' | 'downloading' | 'verifying' | 'extracting';
|
||||
|
||||
/** Neither call has a default deadline, so a hung network would stall install. */
|
||||
const RELEASES_TIMEOUT_MS = 30_000;
|
||||
const DOWNLOAD_TIMEOUT_MS = 300_000;
|
||||
|
||||
export interface InstallProgress {
|
||||
stage: InstallStage;
|
||||
/** 0-1 during download, otherwise null. */
|
||||
@@ -119,6 +123,7 @@ export async function ensureBridgeBinaries(options: EnsureBridgeOptions): Promis
|
||||
options.onProgress?.({ stage: 'locating', progress: null });
|
||||
const releasesResponse = await fetchImpl(BUNDLE_RELEASES_URL, {
|
||||
headers: { Accept: 'application/vnd.github+json' },
|
||||
signal: AbortSignal.timeout(RELEASES_TIMEOUT_MS),
|
||||
});
|
||||
if (!releasesResponse.ok) {
|
||||
throw new Error(`Could not list anime bridge releases (${releasesResponse.status}).`);
|
||||
@@ -129,7 +134,9 @@ export async function ensureBridgeBinaries(options: EnsureBridgeOptions): Promis
|
||||
}
|
||||
|
||||
options.onProgress?.({ stage: 'downloading', progress: 0 });
|
||||
const downloadResponse = await fetchImpl(asset.downloadUrl);
|
||||
const downloadResponse = await fetchImpl(asset.downloadUrl, {
|
||||
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS),
|
||||
});
|
||||
if (!downloadResponse.ok) {
|
||||
throw new Error(`Downloading the anime bridge failed (${downloadResponse.status}).`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user