Objective
The platform frontend has three image-download features (see AlertImages.tsx):
| Mode |
Method |
Needs CORS? |
| 1 — download current image |
native <a download> |
No (browser navigation, no XHR) |
| 2 — download all as ZIP |
fetch(detection.url) → JSZip |
Yes |
| 3 — download all + bounding boxes |
fetch(detection.url) → canvas |
Yes |
Modes 2 and 3 use native fetch() against the presigned S3 URLs. Because these are
cross-origin requests to the object storage host, the browser requires the S3 response to
carry an Access-Control-Allow-Origin header. Today our buckets are created with no CORS
configuration (S3Service.create_bucket only calls create_bucket, nothing else), so both
buttons fail.
Proposed change
- Add a new config setting
S3_CORS_ORIGINS (comma-separated → List[str]) listing the
allowed frontend origins (prod, dev, localhost dev). Default ["*"] for local/dev.
- Extend
S3Service.create_bucket to apply a CORS policy via put_bucket_cors right after
the bucket is created:
AllowedMethods: ["GET", "HEAD"] (browser only reads images; uploads are server-side)
AllowedOrigins: settings.S3_CORS_ORIGINS
AllowedHeaders: ["*"], ExposeHeaders: ["Content-Length", "Content-Type"],
MaxAgeSeconds: 3000
- Add a test (LocalStack) asserting
get_bucket_cors returns the expected rules after
creation.
⚠️ Deployed environments -> retroactive backfill required
create_bucket only runs at organization creation, so this change applies to new orgs
only. Existing buckets on the cloud provider will keep having no CORS policy. Once the
mechanism is validated, we must run a one-off retroactive script that applies
put_bucket_cors to every already-existing bucket. Track this as a follow-up step before
considering the issue done in prod.
[ ] Open point to confirm
Most S3-compatible object storage providers support the standard CORS API, but behavior
varies. We should verify with a get_bucket_cors read against a real bucket that the policy
is actually stored (and that we are hitting the provider's S3-compatible endpoint, not a
legacy Swift-style one).
Objective
The platform frontend has three image-download features (see
AlertImages.tsx):<a download>fetch(detection.url)→ JSZipfetch(detection.url)→ canvasModes 2 and 3 use native
fetch()against the presigned S3 URLs. Because these arecross-origin requests to the object storage host, the browser requires the S3 response to
carry an
Access-Control-Allow-Originheader. Today our buckets are created with no CORSconfiguration (
S3Service.create_bucketonly callscreate_bucket, nothing else), so bothbuttons fail.
Proposed change
S3_CORS_ORIGINS(comma-separated →List[str]) listing theallowed frontend origins (prod, dev, localhost dev). Default
["*"]for local/dev.S3Service.create_bucketto apply a CORS policy viaput_bucket_corsright afterthe bucket is created:
AllowedMethods: ["GET", "HEAD"](browser only reads images; uploads are server-side)AllowedOrigins: settings.S3_CORS_ORIGINSAllowedHeaders: ["*"],ExposeHeaders: ["Content-Length", "Content-Type"],MaxAgeSeconds: 3000get_bucket_corsreturns the expected rules aftercreation.
create_bucketonly runs at organization creation, so this change applies to new orgsonly. Existing buckets on the cloud provider will keep having no CORS policy. Once the
mechanism is validated, we must run a one-off retroactive script that applies
put_bucket_corsto every already-existing bucket. Track this as a follow-up step beforeconsidering the issue done in prod.
[ ] Open point to confirm
Most S3-compatible object storage providers support the standard CORS API, but behavior
varies. We should verify with a
get_bucket_corsread against a real bucket that the policyis actually stored (and that we are hitting the provider's S3-compatible endpoint, not a
legacy Swift-style one).