fix: round 2 S3 audit — CRITICAL SigV4 payload hash bug, timeouts, Content-MD5/Length validation
Deploy FileDrop / deploy (push) Successful in 43s

CRITICAL:
- SigV4 canonical request used sha256Hex('') instead of x-amz-content-sha256
  header value — every PUT/POST with body would fail 403. Now uses the
  signed header value for canonical request, verifyBodyHash after streaming
  for integrity.

HIGH:
- Add 30s AbortSignal.timeout to all Telegram CDN fetches in object-stream.ts
  (previously could hang indefinitely, exhausting connection pool)

MEDIUM:
- Content-MD5 validation: compute and compare when header is present
- Content-Length validation: reject if actual body size != header
- max-keys=0 clamping: enforce minimum of 1 per S3 spec

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude
2026-07-29 08:22:45 +07:00
parent e1e228430f
commit de7d276245
4 changed files with 58 additions and 11 deletions
+5 -4
View File
@@ -282,10 +282,11 @@ export const verifySignature = async (
return { isValid: false, credential: null, errorCode: 'NotImplemented' };
}
// H4: Compute hash from actual body instead of trusting header blindly.
// For streaming bodies (body === null), we cannot hash at this point —
// the caller (controller) must verify body hash after streaming.
const hashedPayload = await getHashedPayload(body);
// CRITICAL: Use the x-amz-content-sha256 header value in the canonical
// request because that's what the client signed. The actual body hash is
// verified by verifyBodyHash() after streaming, ensuring integrity without
// breaking SigV4.
const hashedPayload = contentSha256 || (await getHashedPayload(body));
const canonicalRequest = buildCanonicalRequest(
method,