bb-plane-fork/apps/api/plane
binarybeach d950222749 binarybeachio: fix presigned-PUT signature mismatch on empty Content-Type
Plane's frontend calls getFileMetaDataForUpload() which uses the file-type
library to sniff MIME from magic bytes. For unsniffable formats (plain text,
.json, .csv, etc.) it returns "" — and that empty string was being threaded
through to S3Storage.generate_presigned_post(), signing the presigned URL
with `Content-Type=""`. Browsers can't reliably send an empty Content-Type
header, so the SigV4 signature never matched and R2 returned 403
SignatureDoesNotMatch. UI showed an opaque upload error.

Two-sided fix:
* apps/api/plane/settings/storage.py — default file_type to
  "application/octet-stream" when empty/None. The signed URL now always has
  a non-empty Content-Type the browser can match.
* packages/services/src/file/helper.ts — generateFileUploadPayload now
  prefers the signed Content-Type from upload_data.fields["Content-Type"]
  over file.type. The browser must send EXACTLY the signed value, not its
  own MIME guess from extension. Belt-and-suspenders defense alongside the
  backend default.

Reproduced empirically against R2 with the new keys 2026-05-01: empty
Content-Type signs, then PUT with `Content-Type: text/plain` returns 403
SignatureDoesNotMatch. With this patch, signing "application/octet-stream"
+ sending it back verbatim returns 200.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 00:30:24 -10:00
..
analytics chore: add copyright (#8584) 2026-01-27 13:54:22 +05:30
api [SILO-1026] feat: add estimates external API endpoints (#8664) 2026-03-30 15:30:02 +05:30
app fix: prevent privilege escalation in project member role updates (GHSA-494h-3rcq-5g3c) (#8833) 2026-04-06 15:54:01 +05:30
authentication binarybeachio: account chooser, brand logo, session convention 2026-04-30 14:51:21 -10:00
bgtasks fix: validate redirects in favicon fetching to prevent SSRF (#8858) 2026-04-06 16:04:43 +05:30
db [SILO-1026] feat: add estimates external API endpoints (#8664) 2026-03-30 15:30:02 +05:30
license [GIT-44] refactor(auth): add PASSWORD_TOO_WEAK error code (#8522) 2026-02-13 18:51:33 +05:30
middleware chore: add copyright (#8584) 2026-01-27 13:54:22 +05:30
seeds/data [WEB-5602] feat: new design system (#8220) 2025-12-12 20:50:14 +05:30
settings binarybeachio: fix presigned-PUT signature mismatch on empty Content-Type 2026-05-01 00:30:24 -10:00
space fix: Member Information Disclosure via Public Endpoint #8646 2026-02-20 18:34:56 +05:30
static [WEB-6420] chore: self-host social icons in project invitation email (#8718) 2026-03-05 18:17:42 +05:30
tests binarybeachio: presigned PUT for uploads (R2/B2 don't implement PostObject) 2026-04-30 17:56:52 -10:00
throttles chore: add copyright (#8584) 2026-01-27 13:54:22 +05:30
utils binarybeachio: presigned PUT for uploads (R2/B2 don't implement PostObject) 2026-04-30 17:56:52 -10:00
web chore: add copyright (#8584) 2026-01-27 13:54:22 +05:30
__init__.py chore: add copyright (#8584) 2026-01-27 13:54:22 +05:30
asgi.py chore: add copyright (#8584) 2026-01-27 13:54:22 +05:30
celery.py chore: add copyright (#8584) 2026-01-27 13:54:22 +05:30
urls.py chore: add copyright (#8584) 2026-01-27 13:54:22 +05:30
wsgi.py chore: add copyright (#8584) 2026-01-27 13:54:22 +05:30