Release v1.4.17 with security fixes, stability hardening and retry improvements
- Fix ZIP path traversal vulnerability (reject entries escaping target dir) - Add single instance lock (prevent data corruption from multiple instances) - Add unhandled exception/rejection handlers (prevent silent crashes) - Fix mainWindow reference cleanup on close - Add second-instance handler to focus existing window - Fix claimTargetPath infinite loop (add 10k iteration bound) - Add duplicate startItem guard (prevent concurrent downloads of same item) - Clone session in getSnapshot to prevent live-reference mutation bugs - Clear stateEmitTimer on clearAll to prevent dangling timer emissions - Add extraction timeout safety (4h deadline with logging) - Add dedicated unrestrict retry system with longer backoff for Mega-Debrid errors - Add log rotation (10MB max, keeps one .old backup) - Fix writeExtractResumeState missing mkdir (prevents crash on deleted dirs) - Fix saveSessionAsync EXDEV cross-device rename with copy fallback Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
ea6301d326
commit
d4dd266f6b
+16
-6
@@ -232,11 +232,16 @@ function readExtractResumeState(packageDir: string): Set<string> {
|
||||
}
|
||||
|
||||
function writeExtractResumeState(packageDir: string, completedArchives: Set<string>): void {
|
||||
const progressPath = extractProgressFilePath(packageDir);
|
||||
const payload: ExtractResumeState = {
|
||||
completedArchives: Array.from(completedArchives).sort((a, b) => a.localeCompare(b))
|
||||
};
|
||||
fs.writeFileSync(progressPath, JSON.stringify(payload, null, 2), "utf8");
|
||||
try {
|
||||
fs.mkdirSync(packageDir, { recursive: true });
|
||||
const progressPath = extractProgressFilePath(packageDir);
|
||||
const payload: ExtractResumeState = {
|
||||
completedArchives: Array.from(completedArchives).sort((a, b) => a.localeCompare(b))
|
||||
};
|
||||
fs.writeFileSync(progressPath, JSON.stringify(payload, null, 2), "utf8");
|
||||
} catch (error) {
|
||||
logger.warn(`ExtractResumeState schreiben fehlgeschlagen: ${String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
function clearExtractResumeState(packageDir: string): void {
|
||||
@@ -582,8 +587,13 @@ function extractZipArchive(archivePath: string, targetDir: string, conflictMode:
|
||||
const mode = effectiveConflictMode(conflictMode);
|
||||
const zip = new AdmZip(archivePath);
|
||||
const entries = zip.getEntries();
|
||||
const resolvedTarget = path.resolve(targetDir);
|
||||
for (const entry of entries) {
|
||||
const outputPath = path.join(targetDir, entry.entryName);
|
||||
const outputPath = path.resolve(targetDir, entry.entryName);
|
||||
if (!outputPath.startsWith(resolvedTarget + path.sep) && outputPath !== resolvedTarget) {
|
||||
logger.warn(`ZIP-Eintrag übersprungen (Path Traversal): ${entry.entryName}`);
|
||||
continue;
|
||||
}
|
||||
if (entry.isDirectory) {
|
||||
fs.mkdirSync(outputPath, { recursive: true });
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user