Skip to main content

Command Palette

Search for a command to run...

How to Fix S3 Bucket CORS Policy

Learn: How to Fix S3 Bucket CORS Policy

Updated
•5 min read•View as Markdown
T

Welcome to TopperBlog! 👋

I'm a tech content creator passionate about helping developers level up their careers and master cutting-edge technologies.

🎯 What I Write About: • AI/ML Engineering & LLMs • Web3 & Blockchain Development
• System Design & Architecture • Interview Preparation (FAANG) • Freelancing & Remote Work • Modern Tech Stacks (Next.js, React, Rust, TypeScript) • Performance Optimization & Best Practices

💼 Mission: Sharing practical, actionable insights that accelerate your tech career and maximize your earning potential.

📚 15+ In-Depth Guides covering everything from earning $10k/month as a freelancer to cracking FAANG interviews.

🌐 Let's connect and grow together in this amazing tech journey!

#TechBlogger #SoftwareEngineering #CareerGrowth #WebDevelopment #AIEngineering

How to Fix S3 Bucket CORS Policy

Understanding the Problem

Cross-Origin Resource Sharing (CORS) is a security mechanism that browsers enforce to prevent unauthorized cross-origin requests. When you're trying to access an Amazon S3 bucket from a web application running on a different domain, you'll encounter CORS errors if the bucket isn't properly configured.

Common CORS Error Symptoms

The most frequent error you'll see in the browser console is:

Access to XMLHttpRequest at 'https://my-bucket.s3.amazonaws.com/file.txt' 
from origin 'https://myapp.com' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

Other variations include:

  • "The CORS protocol does not allow specifying a wildcard (*) for the Access-Control-Allow-Credentials header"
  • "The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'"
  • "Method not allowed in CORS policy"

These errors indicate that your S3 bucket's CORS configuration doesn't match your application's requirements.

Why CORS Matters

CORS policies protect users by preventing malicious websites from accessing resources on other domains without permission. However, legitimate cross-origin requests—like a web app hosted on one domain accessing assets in an S3 bucket—need explicit permission through proper CORS configuration.


The Solution

Step 1: Access Your S3 Bucket Settings

  1. Log into the AWS Management Console
  2. Navigate to S3 and select your bucket
  3. Click on the Permissions tab
  4. Scroll down to find CORS section

Step 2: Configure CORS Policy

Click Edit in the CORS section and add your CORS configuration. Here's a basic example:

[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
    "AllowedOrigins": ["https://myapp.com"],
    "ExposeHeaders": ["ETag", "x-amz-version-id"],
    "MaxAgeSeconds": 3000
  }
]

Step 3: Understand Each Parameter

AllowedOrigins: Specifies which domains can access your bucket

  • Use specific domains: "https://myapp.com"
  • Use wildcard for development: "*" (not recommended for production)
  • Support multiple origins: ["https://myapp.com", "https://app.example.com"]

AllowedMethods: HTTP methods permitted for cross-origin requests

  • GET: Reading objects
  • PUT: Uploading objects
  • POST: Form uploads
  • DELETE: Removing objects
  • HEAD: Retrieving object metadata

AllowedHeaders: Headers clients can send in requests

  • "*": Allow all headers
  • Specific headers: ["Content-Type", "Authorization", "x-amz-*"]

ExposeHeaders: Headers the browser allows JavaScript to access

  • Common values: ["ETag", "x-amz-version-id", "x-amz-request-id"]
  • Without this, JavaScript can't read these response headers

MaxAgeSeconds: Browser cache duration for preflight requests

  • Reduces preflight requests for repeated operations
  • Typical range: 3000-86400 seconds

Step 4: Save and Verify

Click Save changes. AWS will validate your JSON syntax. If there are errors, you'll see a message indicating the issue.

Step 5: Test Your Configuration

Use curl to test your CORS setup:

curl -H "Origin: https://myapp.com" \
  -H "Access-Control-Request-Method: GET" \
  -H "Access-Control-Request-Headers: Content-Type" \
  -X OPTIONS \
  https://my-bucket.s3.amazonaws.com/test-file.txt -v

Look for these response headers:

  • Access-Control-Allow-Origin: https://myapp.com
  • Access-Control-Allow-Methods: GET, PUT, POST, DELETE, HEAD
  • Access-Control-Allow-Headers: *

Practical Examples

Example 1: Simple Read-Only Access

For a website that only reads images and documents:

[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET", "HEAD"],
    "AllowedOrigins": ["https://mywebsite.com"],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3000
  }
]

Example 2: Development Environment

For local development with multiple origins:

[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
    "AllowedOrigins": ["http://localhost:3000", "http://localhost:8080"],
    "ExposeHeaders": ["ETag", "x-amz-version-id"],
    "MaxAgeSeconds": 3000
  }
]

Example 3: Multiple Production Domains

[
  {
    "AllowedHeaders": ["Content-Type", "Authorization"],
    "AllowedMethods": ["GET", "PUT", "POST"],
    "AllowedOrigins": [
      "https://app.example.com",
      "https://admin.example.com",
      "https://cdn.example.com"
    ],
    "ExposeHeaders": ["ETag", "x-amz-request-id"],
    "MaxAgeSeconds": 86400
  }
]

Essential Tips and Best Practices

Security Considerations

Avoid Wildcard Origins in Production: Using "*" for AllowedOrigins is convenient but risky. Any website can access your bucket. Always specify exact domains.

Restrict Headers and Methods: Only allow the HTTP methods and headers your application actually needs. This reduces your attack surface.

Use HTTPS: Always use HTTPS origins in production. HTTP origins are less secure and may not work with modern browsers.

Performance Optimization

Increase MaxAgeSeconds Appropriately: Higher values reduce preflight requests but mean changes take longer to propagate. For stable configurations, use 86400 (24 hours).

Minimize Exposed Headers: Only expose headers your JavaScript actually needs. This keeps responses lean and improves performance.

Debugging Techniques

Check Browser Console: The browser's developer tools show exactly which CORS headers are missing or mismatched.

Enable S3 Access Logs: Configure S3 access logging to see all requests and identify patterns in failed requests.

Use AWS CloudTrail: Monitor API calls to your bucket to ensure CORS changes are being applied correctly.

Common Mistakes to Avoid

Forgetting Protocol: https://myapp.com and http://myapp.com are different origins. Include the protocol.

Typos in Domain Names: A single character difference means the origin won't match. Double-check your domain names.

Not Including Necessary Headers: If your application sends custom headers, add them to AllowedHeaders or requests will fail.

Misconfiguring ExposeHeaders: If JavaScript needs to read response headers, they must be listed here or the browser will block access.

Assuming Wildcard Methods Work: Some configurations require specific methods. Test each operation individually.

Advanced Configuration

Wildcard Patterns: S3 CORS doesn't support wildcard patterns like https://*.example.com. You must list each subdomain explicitly.

Credentials and Cookies: If your requests include credentials, set AllowedOrigins to specific domains (not *) and ensure your application handles authentication properly.

CloudFront Integration: If using CloudFront in front of S3, configure CORS on the S3 bucket, not CloudFront.


Verification Checklist

Before considering your CORS configuration complete:

  • [ ] CORS policy is saved in the S3 bucket
  • [ ] AllowedOrigins matches your application's domain exactly
  • [ ] AllowedMethods includes all HTTP verbs your app uses
  • [ ] AllowedHeaders includes any custom headers your app sends
  • [ ] ExposeHeaders includes headers your JavaScript reads
  • [ ] Tested with curl or Postman to verify headers
  • [ ] Tested from your actual application in the browser
  • [ ] Browser console shows no CORS errors
  • [ ] All required operations (GET, PUT, DELETE, etc.) work
  • [ ] Configuration follows security best practices

Conclusion

Fixing S3 bucket CORS issues involves understanding the security mechanism, properly configuring your policy with appropriate origins and methods, and thoroughly testing your setup. Start with a restrictive configuration and gradually expand permissions as needed. Always prioritize security by avoiding wildcards in production and only exposing necessary headers and methods. With these guidelines, you'll resolve CORS errors and maintain a secure, functional S3 integration with your web applications.