This commit is contained in:
Zimeng Xiong
2026-02-06 22:49:21 -08:00
parent ea06cd9175
commit 7aa33a1bdf
+7 -29
View File
@@ -164,10 +164,10 @@ const isPathInsideDirectory = (candidatePath: string, rootDir: string): boolean
}; };
const isSafeMulterTempFilename = (value: string): boolean => const isSafeMulterTempFilename = (value: string): boolean =>
/^[a-f0-9]{32}$/i.test(value); /^[a-f0-9]{32}$/.test(value);
const resolveSafeUploadedFilePath = async ( const resolveSafeUploadedFilePath = async (
fileMeta: { filename?: unknown; destination?: unknown }, fileMeta: { filename?: unknown },
uploadRoot: string uploadRoot: string
): Promise<string> => { ): Promise<string> => {
const absoluteUploadRoot = path.resolve(uploadRoot); const absoluteUploadRoot = path.resolve(uploadRoot);
@@ -179,17 +179,6 @@ const resolveSafeUploadedFilePath = async (
throw new ImportValidationError("Invalid upload path"); throw new ImportValidationError("Invalid upload path");
} }
if (typeof fileMeta.destination === "string" && fileMeta.destination.trim().length > 0) {
try {
const canonicalDestination = await fsPromises.realpath(path.resolve(fileMeta.destination));
if (canonicalDestination !== canonicalUploadRoot) {
throw new ImportValidationError("Invalid upload path");
}
} catch {
throw new ImportValidationError("Invalid upload path");
}
}
const filename = typeof fileMeta.filename === "string" ? fileMeta.filename : ""; const filename = typeof fileMeta.filename === "string" ? fileMeta.filename : "";
if (!isSafeMulterTempFilename(filename)) { if (!isSafeMulterTempFilename(filename)) {
throw new ImportValidationError("Invalid upload path"); throw new ImportValidationError("Invalid upload path");
@@ -200,18 +189,7 @@ const resolveSafeUploadedFilePath = async (
throw new ImportValidationError("Invalid upload path"); throw new ImportValidationError("Invalid upload path");
} }
let canonicalFilePath = joinedPath; return joinedPath;
try {
canonicalFilePath = await fsPromises.realpath(joinedPath);
} catch {
throw new ImportValidationError("Invalid upload path");
}
if (!isPathInsideDirectory(canonicalFilePath, canonicalUploadRoot)) {
throw new ImportValidationError("Invalid upload path");
}
return canonicalFilePath;
}; };
const openReadonlySqliteDb = (filePath: string): any => { const openReadonlySqliteDb = (filePath: string): any => {
@@ -401,7 +379,7 @@ Drawings: ${drawings.length}
let stagedPath: string; let stagedPath: string;
try { try {
stagedPath = await resolveSafeUploadedFilePath( stagedPath = await resolveSafeUploadedFilePath(
{ filename: req.file.filename, destination: req.file.destination }, { filename: req.file.filename },
uploadDir uploadDir
); );
} catch (error) { } catch (error) {
@@ -492,7 +470,7 @@ Drawings: ${drawings.length}
let stagedPath: string; let stagedPath: string;
try { try {
stagedPath = await resolveSafeUploadedFilePath( stagedPath = await resolveSafeUploadedFilePath(
{ filename: req.file.filename, destination: req.file.destination }, { filename: req.file.filename },
uploadDir uploadDir
); );
} catch (error) { } catch (error) {
@@ -752,7 +730,7 @@ Drawings: ${drawings.length}
let stagedPath: string; let stagedPath: string;
try { try {
stagedPath = await resolveSafeUploadedFilePath( stagedPath = await resolveSafeUploadedFilePath(
{ filename: req.file.filename, destination: req.file.destination }, { filename: req.file.filename },
uploadDir uploadDir
); );
} catch (error) { } catch (error) {
@@ -841,7 +819,7 @@ Drawings: ${drawings.length}
let stagedPath: string; let stagedPath: string;
try { try {
stagedPath = await resolveSafeUploadedFilePath( stagedPath = await resolveSafeUploadedFilePath(
{ filename: req.file.filename, destination: req.file.destination }, { filename: req.file.filename },
uploadDir uploadDir
); );
} catch (error) { } catch (error) {