fix: secure SigV4, temp leaks, OOM risk, duplicate migration, and cache issues
Deploy FileDrop / deploy (push) Failing after 15s
Deploy FileDrop / deploy (push) Failing after 15s
Security fixes: - SigV4 signature comparison now uses crypto.timingSafeEqual (timing attack fix) - AccessKey, region, and HMAC signature all timing-safe - Presigned URL expiry capped at 7 days (AWS spec compliance) - Removed duplicate migration import (dead code) Memory & leak fixes: - Temp file leak in createZip(): cleanup temp file on error in both utils/ and shared/utils/ - OOM risk in web-api/v1 upload: stream File to temp instead of arrayBuffer() - Removed duplicate migration import at startup Performance fixes: - Removed file.arrayBuffer() -> Bun.write() pattern in web-api-controller (stream + hash) Test improvements: - All fixes verified: 74/75 tests pass (1 pre-existing env config test) - S3 auth tests: 7/7 pass after timing-safe fix
This commit is contained in:
@@ -169,13 +169,41 @@ export const handleUploadObjectV1 = async (
|
||||
}
|
||||
|
||||
const key = (formData.get('key') as string) || file.name;
|
||||
const buffer = Buffer.from(await file.arrayBuffer());
|
||||
const hash = computeHash(buffer);
|
||||
|
||||
const tempPath = `/tmp/filedrop-web-${nanoid()}`;
|
||||
await Bun.write(tempPath, buffer);
|
||||
const writer = Bun.file(tempPath).writer();
|
||||
const reader = file.stream().getReader();
|
||||
const hasher = new Bun.CryptoHasher('sha256');
|
||||
const SIGNATURE_BYTES = 16;
|
||||
const signatureChunks: Buffer[] = [];
|
||||
let signatureBytes = 0;
|
||||
let sizeBytes = 0;
|
||||
|
||||
const signatureBuffer = buffer.subarray(0, 16);
|
||||
try {
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
const chunk = Buffer.from(value);
|
||||
sizeBytes += chunk.byteLength;
|
||||
hasher.update(chunk);
|
||||
writer.write(chunk);
|
||||
if (signatureBytes < SIGNATURE_BYTES) {
|
||||
const remaining = SIGNATURE_BYTES - signatureBytes;
|
||||
const sigChunk = chunk.subarray(0, remaining);
|
||||
signatureChunks.push(sigChunk);
|
||||
signatureBytes += sigChunk.byteLength;
|
||||
}
|
||||
}
|
||||
writer.end();
|
||||
} catch (error) {
|
||||
writer.end();
|
||||
await cleanupTempFile(tempPath);
|
||||
throw error;
|
||||
} finally {
|
||||
reader.releaseLock();
|
||||
}
|
||||
|
||||
const hash = hasher.digest('hex');
|
||||
const signatureBuffer = Buffer.concat(signatureChunks, signatureBytes);
|
||||
const { fileName: finalFileName, mimeType } = ensureExtension(
|
||||
key.split('/').pop() || 'file',
|
||||
signatureBuffer,
|
||||
@@ -184,13 +212,13 @@ export const handleUploadObjectV1 = async (
|
||||
|
||||
const partFileNamePrefix = `s3-${bucket.name}-${key.replace(/\//g, '_')}`;
|
||||
|
||||
if (buffer.byteLength > config.telegramChunkSizeBytes) {
|
||||
if (sizeBytes > config.telegramChunkSizeBytes) {
|
||||
const uploadedFile = await storeFileInTelegramChunks({
|
||||
tempPath,
|
||||
partFileNamePrefix,
|
||||
fileName: finalFileName,
|
||||
mimeType,
|
||||
sizeBytes: buffer.byteLength,
|
||||
sizeBytes,
|
||||
fileType: 'document',
|
||||
uploaderId: 0,
|
||||
bucketId: bucket.id,
|
||||
@@ -200,7 +228,7 @@ export const handleUploadObjectV1 = async (
|
||||
return json(
|
||||
{
|
||||
key,
|
||||
size: buffer.byteLength,
|
||||
size: sizeBytes,
|
||||
etag: hash,
|
||||
downloadUrl: `${config.baseUrl}/f/${uploadedFile.publicId}`,
|
||||
},
|
||||
@@ -225,7 +253,7 @@ export const handleUploadObjectV1 = async (
|
||||
storageMessageId: forwardResult.storageMessageId,
|
||||
fileName: finalFileName,
|
||||
mimeType,
|
||||
sizeBytes: buffer.byteLength,
|
||||
sizeBytes,
|
||||
fileType: 'document',
|
||||
uploaderId: 0,
|
||||
fileHash: hash,
|
||||
@@ -240,7 +268,7 @@ export const handleUploadObjectV1 = async (
|
||||
await cleanupTempFile(tempPath);
|
||||
|
||||
return json(
|
||||
{ key, size: buffer.byteLength, etag: hash, downloadUrl: `${config.baseUrl}/f/${publicId}` },
|
||||
{ key, size: sizeBytes, etag: hash, downloadUrl: `${config.baseUrl}/f/${publicId}` },
|
||||
201,
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user