How to Configure S3 Bucket CORS to Allow Cross-Origin Requests from a Specific Domain
To configure S3 bucket CORS for a specific domain, use the PutBucketCorsCommand in the AWS SDK for JavaScript v3 to upload a CORSConfiguration containing a rule with AllowedOrigins set to your domain.
When building web applications that interact directly with Amazon S3 from the browser, you must configure Cross-Origin Resource Sharing (CORS) policies on your buckets. The AWS SDK for JavaScript v3 provides precise control over these policies through the PutBucketCorsCommand and related types defined in the S3 client.
Understanding S3 CORS Rule Evaluation
S3 stores CORS configurations as XML documents on the bucket's ?cors sub-resource. When a browser sends a cross-origin request, S3 evaluates the rules in the order they are defined and applies the first rule that matches the request's Origin header, HTTP method, and request headers.
According to the source code in clients/client-s3/src/commands/PutBucketCorsCommand.ts (lines 34-45), this first-match behavior means you should place the most restrictive, domain-specific rules before broader wildcard rules to ensure only intended origins receive access.
Configure S3 Bucket CORS Using PutBucketCorsCommand
The SDK exposes two primary patterns for applying CORS configurations: the low-level command interface and the higher-level helper method.
Low-Level Command Approach
Use PutBucketCorsCommand when you need explicit control over the command lifecycle or when working with the modular client architecture.
import { S3Client, PutBucketCorsCommand } from "@aws-sdk/client-s3";
const client = new S3Client({ region: "us-east-1" });
const corsConfiguration = {
CORSRules: [
{
// Restrict to specific domain only
AllowedOrigins: ["https://app.example.com"],
// HTTP methods permitted from this origin
AllowedMethods: ["GET", "PUT", "POST"],
// Headers allowed in the request
AllowedHeaders: ["*"],
// Response headers exposed to the browser
ExposeHeaders: ["x-amz-request-id", "x-amz-server-side-encryption"],
// Cache preflight response for 1 hour
MaxAgeSeconds: 3600,
},
],
};
await client.send(
new PutBucketCorsCommand({
Bucket: "my-public-bucket",
CORSConfiguration: corsConfiguration,
})
);
The TypeScript interfaces for CORSConfiguration and CORSRule are defined in clients/client-s3/src/models/models_0.ts, ensuring type safety when constructing these objects.
High-Level Helper Method
For simpler scripts, the S3 client instance provides a putBucketCors method that wraps the command.
import { S3Client } from "@aws-sdk/client-s3";
const s3 = new S3Client({ region: "us-east-1" });
await s3.putBucketCors({
Bucket: "my-public-bucket",
CORSConfiguration: {
CORSRules: [
{
AllowedOrigins: ["https://app.example.com"],
AllowedMethods: ["GET"],
AllowedHeaders: ["*"],
ExposeHeaders: ["x-amz-server-side-encryption"],
MaxAgeSeconds: 3000,
},
],
},
});
The end-to-end test suite in clients/client-s3/test/e2e/s3-bucket-features.e2e.spec.ts (lines 34-45) demonstrates this exact pattern, validating that the configuration persists correctly on the bucket.
Verifying Your S3 CORS Configuration
After applying the configuration, retrieve it using GetBucketCorsCommand or s3.getBucketCors to confirm the rules are active.
const result = await s3.getBucketCors({ Bucket: "my-public-bucket" });
console.log(JSON.stringify(result.CORSRules, null, 2));
The response should contain the AllowedOrigins array with your specific domain, confirming that S3 will reject cross-origin requests from unauthorized origins while allowing your designated domain.
Summary
- Use
PutBucketCorsCommand(ors3.putBucketCors) to upload CORS rules to an S3 bucket via the AWS SDK for JavaScript v3. - Specify the exact domain in the
AllowedOriginsarray of yourCORSRuleto restrict access to a single origin. - Order matters: S3 applies the first matching rule, so place specific domain rules before wildcard rules.
- Verify the configuration with
GetBucketCorsCommandto ensure the policy is active.
Frequently Asked Questions
What is the correct format for AllowedOrigins when configuring S3 CORS?
The AllowedOrigins field must contain the complete origin string including the protocol, domain, and port (if non-standard). For example, use https://app.example.com rather than just app.example.com. According to the SDK source in clients/client-s3/src/models/models_0.ts, this is an array of strings where each entry represents one permitted origin.
How does S3 handle multiple CORS rules in the same configuration?
S3 evaluates CORS rules in the order they are defined in the CORSRules array and applies the first rule that matches the request's origin, method, and headers. As documented in clients/client-s3/src/commands/PutBucketCorsCommand.ts, this first-match behavior means you should structure your rules from most specific to most general to prevent unintended access.
Why is my S3 CORS configuration not working for my specific domain?
Common issues include: omitting the protocol (http vs https) in AllowedOrigins, not including the specific HTTP method in AllowedMethods, or having a more permissive rule earlier in the CORSRules array that matches first. Verify your configuration using GetBucketCorsCommand and check the browser's developer console for the exact preflight error to identify which CORS header is missing.
Can I use wildcards in AllowedOrigins when configuring S3 CORS?
While S3 supports the wildcard * in AllowedOrigins to allow any domain, you cannot use partial wildcards like https://*.example.com. For specific subdomain patterns, you must list each subdomain explicitly or use a single wildcard for all origins. The SDK's CORSRule interface in clients/client-s3/src/models/models_0.ts treats AllowedOrigins as a string array where * is a valid entry but regex patterns are not supported.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →