From eefb536cb3a37915cdcc4101367a2c2d70a74db1 Mon Sep 17 00:00:00 2001 From: Sucukdeluxe Date: Tue, 3 Mar 2026 02:25:10 +0100 Subject: [PATCH] Fix path traversal false positive: skip subst drive mapping for JVM backend Java's getCanonicalFile() resolves subst drives inconsistently, causing secureResolve() to falsely block valid filenames. JVM handles long paths natively so subst is only needed for legacy UnRAR/7z. Co-Authored-By: Claude Opus 4.6 --- package.json | 2 +- src/main/extractor.ts | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 2b1ec6f..70e201d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "real-debrid-downloader", - "version": "1.5.45", + "version": "1.5.46", "description": "Real-Debrid Downloader Desktop (Electron + React + TypeScript)", "main": "build/main/main/main.js", "author": "Sucukdeluxe", diff --git a/src/main/extractor.ts b/src/main/extractor.ts index 50b1d1e..d763112 100644 --- a/src/main/extractor.ts +++ b/src/main/extractor.ts @@ -1151,9 +1151,10 @@ async function runExternalExtract( await fs.promises.mkdir(targetDir, { recursive: true }); // On Windows, long targetDir + archive internal paths can exceed MAX_PATH (260 chars). - // Use "subst" to map the targetDir to a short drive letter for the extraction process. - const subst = createSubstMapping(targetDir); - const effectiveTargetDir = subst ? `${subst.drive}:` : targetDir; + // Use "subst" to map the targetDir to a short drive letter for the legacy extraction process. + // JVM does NOT use subst — Java handles long paths natively and subst causes + // false-positive path traversal errors in secureResolve (getCanonicalFile inconsistency). + let subst: SubstMapping | null = null; try { if (backendMode !== "legacy") { @@ -1169,7 +1170,7 @@ async function runExternalExtract( const jvmResult = await runJvmExtractCommand( layout, archivePath, - effectiveTargetDir, + targetDir, conflictMode, passwordCandidates, onArchiveProgress, @@ -1196,6 +1197,10 @@ async function runExternalExtract( } } + // subst only needed for legacy UnRAR/7z (MAX_PATH limit) + subst = createSubstMapping(targetDir); + const effectiveTargetDir = subst ? `${subst.drive}:` : targetDir; + const command = await resolveExtractorCommand(); const password = await runExternalExtractInner( command,