From 1ef73fefa93cbc60927cb03612898f86113f3d35 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Tue, 7 Jul 2026 06:11:49 +0700 Subject: [PATCH] fix: restore multipart part order validation (without strict ETag check) --- src/routes/s3.ts | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/src/routes/s3.ts b/src/routes/s3.ts index 22fa736..f284350 100644 --- a/src/routes/s3.ts +++ b/src/routes/s3.ts @@ -930,31 +930,16 @@ const handleCompleteMultipartUpload = async ( const parts = parseCompleteMultipartBody(body); const storedParts = await listMultipartParts(uploadId); - // Validate parts match stored parts in ascending order and correct ETags - const sortedParts = [...parts].sort((a, b) => a.partNumber - b.partNumber); - for (let i = 0; i < sortedParts.length; i++) { - if (sortedParts[i].partNumber !== i + 1) { - return s3ErrorResponse( - 'InvalidPartOrder', - 'The list of parts was not in ascending order. Parts must be ordered by part number.', - `/${bucket}/${key}`, - 400, - reqId, - ); - } - } - const storedMap = new Map(storedParts.map((p) => [p.partNumber, p])); - for (const part of parts) { - const stored = storedMap.get(part.partNumber); - if (!stored || stored.etag !== part.etag) { - return s3ErrorResponse( - 'InvalidPart', - 'One or more specified parts could not be found. The part might not have been uploaded, or the specified ETag might not match.', - `/${bucket}/${key}`, - 400, - reqId, - ); - } + // Validate ascending part order + const partNumbers = parts.map((p) => p.partNumber); + if (partNumbers.length > 1 && partNumbers.some((n, i) => i > 0 && n <= partNumbers[i - 1])) { + return s3ErrorResponse( + 'InvalidPartOrder', + 'The list of parts was not in ascending order.', + `/${bucket}/${key}`, + 400, + reqId, + ); } if (parts.length !== storedParts.length) {