Configure bucket CORS
Coming from another cloud?
▸AWS·Amazon S3
This Quake AI feature maps to AWS’s Amazon S3.
▸Azure·Blob Storage
This Quake AI feature maps to Azure’s Blob Storage.
▸DigitalOcean·Space (bucket)
Space (bucket)
- Naming differs: users create a “Space” that is a bucket, and each bucket has a unique URL (virtual-hosted or path style), whereas Swift uses containers within an account namespace. ().
- Bucket addressing uses S3-style endpoints such as `${BUCKET}.${REGION}.digitaloceanspaces.com` (and `${REGION}.digitaloceanspaces.com/${BUCKET}`), which differs from Swift’s account/container/object path conventions. (, ).
- Access keys can be scoped to high-level permission tiers (Read, Read/Write/Delete, All) applied across buckets/objects, which differs from Swift’s typical tenant/user + container ACL model. ().
▸Google Cloud·Storage
This Quake AI feature maps to Google Cloud’s Storage.
▸Hetzner·Buckets
Buckets
- S3 API (PUT Bucket requires specific headers like x-amz-acl limited to private/public-read, LocationConstraint); Swift uses POST/PUT Container with broader ACLs via X-Container-Read/Write.
- Public access via https://bucket.location.your-objectstorage.com/object; Swift public via temp URLs or ACLs.
- Up to 100 buckets per account; Swift has no hard limit.
Setting up CORS on a S3 Bucket
CORS, or Cross-Origin Resource Sharing, is a security feature built into your web browser that decides whether to allow a website to access resources from a different website. Think of it as your browser's own security guard, making sure you don't receive dangerous or unauthorized content.
What CORS does#
Imagine you're on a website, let's say my-party.com. A script on this site wants to grab some data from another website, their-party.com.
-
The Request: Your browser sends a request to
their-party.comasking for the data. The request includes a special "Origin" note that says, "Hey, I'm from my-party.com." -
The Server's Response: The server at
their-party.comreceives the request. The server doesn't block it; it responds with the data as requested. However, it also adds an extra header, a little stamp of approval, that lists which websites are allowed to use this data. This stamp is called theAccess-Control-Allow-Originheader. -
The Browser's Decision: This is the most crucial step. When the response arrives back, your browser looks at that stamp of approval.
If the stamp says my-party.com is on the allowed list, your browser says, "Okay, this is safe," and passes the data on to the website to use.
If the stamp is missing, or it lists a different website, your browser's security guard immediately steps in. It will block the data from being used by my-party.com and throw a CORS error.
The key point is that the server didn't deny the request; your browser did. The server didn't provide the necessary permission slip for the data to be used by an outside source.
When is CORS needed#
This browser-enforced rule is triggered anytime a website tries to access a resource from a different origin. An origin is defined by the combination of the protocol (http or https), the domain (example.com), and the port number (80 or 443).
For example, your browser will trigger a CORS check if https://example.com tries to access data from:
http://example.com (❌ Different protocol)
https://api.example.com (❌ Different subdomain)
https://example.com:8080 (❌ Different port)
In all these cases, the browser will look for that special approval stamp from the server. Without it, the browser will block the resource, protecting you from cross-site data theft.
How CORS works#
-
Same-Origin Policy: By default, browsers prevent web pages from making requests to a different origin (domain, scheme, or port) than the one it was loaded from.
-
CORS Mechanism: CORS introduces HTTP headers that allow a server to explicitly list which other origins are allowed to access its resources.
-
Preflight Requests: For certain requests, the browser performs a "preflight" request to the server to check if the actual request is allowed. This preflight request uses the HTTP OPTIONS method to ask the server if the subsequent request is permitted.
-
Server Response: If the server's response includes the necessary CORS headers (like Access-Control-Allow-Origin) and permits the origin, the browser allows the actual request to proceed; otherwise, it blocks it.
What does a CORS policy look like#
Below is a simple CORS policy in json
{
"CORSRules": [
{
"AllowedOrigins": ["http://www.example.com"],
"AllowedHeaders": ["*"],
"AllowedMethods": [
"GET"
],
"MaxAgeSeconds": 3000,
"ExposeHeaders": []
}
]
}Below is a simple CORS policy in xml
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>http://www.example.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>You can apply this to your bucket with s3cmd like this (s3cmd ONLY accepts xml formatted CORS policies)
s3cmd setcors /path/to/cors.xml s3://your-bucket-nameYou can view the buckets CORS policy with s3cmd like this
s3cmd info s3://your-bucket-nameYou can apply this to your bucket with the awscli like this
aws s3api put-bucket-cors \
--bucket your-bucket-name \
--cors-configuration file://cors.json \
--endpoint-url "https://object.us-east-1.rumble.cloud"You can view your buckets current cors policy with awscli like this
aws s3api get-bucket-cors \
--bucket your-bucket-name \
--endpoint-url "https://object.us-east-1.rumble.cloud"Common pitfalls#
Not specifying the tenant ID in the URL for the resource#
CORS preflight requests are not authenticated so you must provide the tenant ID in the URL that is provided to the users browser for the requested resource. This is different than many other s3 providers but allows you the freedom to name your bucket without worrying about another user taking the bucket name you wanted.
URLs for resources should look like this
https://object.${region}.rumble.cloud/${tenant_id}:bucket/${object}For example:
https://object.us-east-2.rumble.cloud/gT2jQ9uX8pA4vY7fH3kL6dN5mB1rC:bucket/CORS.jpgSome common CORS policy mistakes include using overly permissive rules, not accounting for preflight requests, and misconfiguring the AllowedHeaders or ExposeHeaders values.
Using overly permissive policies#
One of the most frequent mistakes is using a wildcard (*) for AllowedOrigin, which weakens a key security feature of CORS. While this is simple to set up, it can make your bucket or API vulnerable. If an attacker can get a user to visit a malicious website, they can make cross-origin requests to your resource and steal sensitive data if your authentication is handled via cookies or other credentials. A better practice is to explicitly list the domains that need access, for example:
"AllowedOrigins": ["https://www.example.com", "https://app.example.com"]Misunderstanding preflight requests#
Many developers don't realize that some complex CORS requests require a separate "preflight" OPTIONS request before the actual request is sent. This preflight request checks with the server to see if the main request is safe to send.
Incorrect AllowedHeaders or ExposeHeaders#
Headers are a frequent source of CORS errors.
-
AllowedHeaders: This specifies which headers the browser can include in a preflight request. If you send a request with a custom header (likeX-My-Custom-Header) but haven't listed it inAllowedHeaders, the preflight request will fail. Many developers use a wildcard * to avoid this, which is again, less secure. -
ExposeHeaders: This is often forgotten. By default, browsers only give your JavaScript access to a limited set of response headers (likeContent-Type). If your server sends a custom response header (for example,X-My-Response-Id) that your code needs to read, you must explicitly list it in the ExposeHeaders section of your policy. If you don't, the browser will receive the header but hide it from your script, leading to silent failures in your application.
Specifying the wrong protocol or port#
An origin is the combination of the protocol, domain, and port. A common mistake is to only specify the domain.
-
http://www.example.com is a different origin from https://www.example.com.
-
https://www.example.com:8080 is a different origin from https://www.example.com.
If your web application is served over HTTPS, but your CORS policy only allows HTTP, all your requests will fail with a CORS error. Always ensure the protocol and port in your policy match the origin of your application.
Testing your CORS policy#
A Quick way to test your CORS policy is to use the curl command like this
curl -i -X OPTIONS -H "Origin: http://www.example.com" -H "Access-Control-Request-Method: GET" "${URL}"Your should see a "200 OK" response that includes the CORS headers if your CORS policy is correct.
HTTP/1.1 200 OK
Date: Wed, 03 Sep 2025 20:24:29 GMT
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Origin: http://www.example.com
Vary: Origin
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
x-amz-request-id: tx0000086b4cac3f4073e5f-0068b8a3fd-47539710-cle9-local
Strict-Transport-Security: max-age=31536000;includeSubDomains;preloadUsage Guidelines
The sample code, software libraries, command line tools, proofs of concept, templates, and other related technology on this page (including any of the foregoing that is provided by Quake AI personnel) is provided to you as Quake AI Content under the Quake AI Customer Agreement, or the relevant written agreement between you and Quake AI (whichever applies). Do not use this Quake AI Content in your production accounts, or on production or other critical data. You are responsible for testing, securing, and optimizing the Quake AI Content (such as sample code) as appropriate for production grade use based on your specific quality control practices and standards. Deploying Quake AI Content may incur Quake AI charges for creating or using Quake AI chargeable resources, such as running Compute instances or storing data in Object Storage. Your use is also subject to the Acceptable Use Policy.
For the full policy, see Usage Guidelines.
Last validated: 08.09.2026
Quick answers
See Also
How to enable versioning on an object storage bucket
Shares: Storage, Containers
How to use CloudFront with object storage buckets
Shares: Storage, Containers
S3 on Quake AI
Prerequisite
How to access an uploaded file in object storage
Shares: Storage, Containers
How to create an object storage bucket
Shares: Storage, Containers