Release v1.4.20 with comprehensive audit fixes (140 issues) and expanded test coverage
- Speed calculation: raised minimum elapsed floor to 0.5s preventing unrealistic spikes - Reconnect: exponential backoff with consecutive counter, clock regression protection - Download engine: retry byte tracking (itemContributedBytes), mkdir before createWriteStream, content-length validation - Fire-and-forget promises: all void promises now have .catch() error handlers - Session recovery: normalize stale active statuses to queued on crash recovery, clear speedBps - Storage: config backup (.bak) before overwrite, EXDEV cross-device rename fallback with type guard - IPC security: input validation on all string/array IPC handlers, CSP headers in production - Main process: clipboard memory limit (50KB), installer timing increased to 800ms - Debrid: attribute-order-independent meta tag regex for Rapidgator filename extraction - Constants: named constants for magic numbers (MAX_MANIFEST_FILE_BYTES, MAX_LINK_ARTIFACT_BYTES, etc.) - Extractor/integrity: use shared constants, document password visibility and TOCTOU limitations - Tests: 103 tests total (55 new), covering utils, storage, integrity, cleanup, extractor, debrid, update Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
556f0672dc
commit
63fd402083
@@ -466,6 +466,10 @@ export function buildExternalExtractArgs(
|
||||
const lower = command.toLowerCase();
|
||||
if (lower.includes("unrar") || lower.includes("winrar")) {
|
||||
const overwrite = mode === "overwrite" ? "-o+" : mode === "rename" ? "-or" : "-o-";
|
||||
// NOTE: The password is passed as a CLI argument (-p<password>), which means it may be
|
||||
// visible via process listing tools (e.g. `ps aux` on Unix). This is unavoidable because
|
||||
// WinRAR/UnRAR CLI does not support password input via stdin or environment variables.
|
||||
// On Windows (the target platform) this is less of a concern than on shared Unix systems.
|
||||
const pass = password ? `-p${password}` : "-p-";
|
||||
const perfArgs = usePerformanceFlags && shouldUseExtractorPerformanceFlags()
|
||||
? ["-idc", extractorThreadSwitch()]
|
||||
@@ -474,6 +478,7 @@ export function buildExternalExtractArgs(
|
||||
}
|
||||
|
||||
const overwrite = mode === "overwrite" ? "-aoa" : mode === "rename" ? "-aou" : "-aos";
|
||||
// NOTE: Same password-in-args limitation as above applies to 7z as well.
|
||||
const pass = password ? `-p${password}` : "-p";
|
||||
return ["x", "-y", overwrite, pass, archivePath, `-o${targetDir}`];
|
||||
}
|
||||
@@ -599,6 +604,9 @@ function extractZipArchive(archivePath: string, targetDir: string, conflictMode:
|
||||
continue;
|
||||
}
|
||||
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
||||
// TOCTOU note: There is a small race between existsSync and writeFileSync below.
|
||||
// This is acceptable here because zip extraction is single-threaded and we need
|
||||
// the exists check to implement skip/rename conflict resolution semantics.
|
||||
if (fs.existsSync(outputPath)) {
|
||||
if (mode === "skip") {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user