Skip to content

S3 BucketOwnerEnforced ACL Conflict ​

AWS introduced significant security changes impacting S3 bucket configurations in April 2023, causing unexpected upload failures with errors like InvalidBucketAclWithObjectOwnership: Bucket cannot have ACLs set with ObjectOwnership's BucketOwnerEnforced setting. This issue manifests as sudden upload failures even in previously working configurations.

Problem Explained ​

AWS disabled ACLs and enabled Block Public Access by default for new buckets starting April 2023. The BucketOwnerEnforced Object Ownership setting:

  • Disables all ACLs
  • Makes bucket owner the exclusive object owner
  • Rejects API requests containing ACL headers (e.g., public-read)
  • Conflicts with bucket ACL configurations

The error occurs when:

  • Your bucket has BucketOwnerEnforced enabled
  • Your application or infrastructure uses ACLs (in bucket settings or API calls)
  • Upload requests include ACL headers like x-amz-acl

Follow AWS's security best practice by discontinuing ACLs completely.

Steps

  1. Remove existing ACL grants
    Delete all non-owner entries from bucket ACLs
  2. Set Object Ownership
    Enable BucketOwnerEnforced via AWS Console or CLI:
    bash
    aws s3api put-bucket-ownership-controls \
      --bucket YOUR_BUCKET_NAME \
      --ownership-controls="Rules=[{ObjectOwnership=BucketOwnerEnforced}]"
  3. Configure public access
    Allow public policies and apply bucket policy:
    bash
    aws s3api put-public-access-block \
      --bucket YOUR_BUCKET_NAME \
      --public-access-block-configuration "BlockPublicAcls=false,BlockPublicPolicy=false"
  4. Apply bucket policy
    Use this policy for public read access:
    json
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "PublicReadGetObject",
          "Effect": "Allow",
          "Principal": "*",
          "Action": "s3:GetObject",
          "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        }
      ]
    }
  5. Remove ACL headers from upload requests
    Ensure SDK/client requests omit ACL parameters like public-read

:fontawesome-solid-gear:{ .manual } Solution 2: Re-enable ACL Support ​

Use this approach if you require ACLs or can't modify application code immediately.

Not Recommended

This retains legacy ACL behavior which AWS plans to deprecate

bash
# 1. Allow ACL usage
aws s3api put-bucket-ownership-controls \
  --bucket YOUR_BUCKET_NAME \
  --ownership-controls="Rules=[{ObjectOwnership=BucketOwnerPreferred}]"

# 2. Set bucket ACL 
aws s3api put-bucket-acl \
  --bucket YOUR_BUCKET_NAME \
  --acl public-read

For CloudFormation users:

yaml
Resources:
  ExampleBucket:
    Type: AWS::S3::Bucket
    Properties:
      OwnershipControls:
        Rules:
          - ObjectOwnership: BucketOwnerPreferred
      PublicAccessBlockConfiguration:
        BlockPublicAcls: false

Critical Fixes for Specific Use Cases ​

Single-Page Applications (SPAs) ​

Add ListBucket permission for client-side routing:

json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::BUCKET/*"
    },
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::BUCKET"
    }
  ]
}

Upload Failures Persisting After Changes ​

Verify your upload code omits ACL headers. Common offenders:

  • SDK parameters like ACL='public-read' (Boto3/Python)
  • x-amz-acl headers in REST API calls
  • CLI flags like --acl public-read

Explanation of Key Changes ​

The root conflict arises from AWS security enhancements:

SettingImpact
BucketOwnerEnforcedDisables all ACLs; requires bucket policies
ObjectWriterAllows object-level ACLs (legacy behavior)
BlockPublicPolicy=falsePermits public bucket policies when using BucketOwnerEnforced

Why This Changed

AWS deprecated ACLs as they grant coarse-grained access and complicate permission management. Bucket policies provide more secure, granular control via IAM principles rather than global permissions.

Best Practices ​

  1. Replace ACLs with bucket policies in all new projects
  2. Audit existing buckets via S3 console > Permissions tab
  3. Remove ACL parameters from all SDK/client code
  4. Enable Block Public Access except where required

Object Ownership OptionsConfiguration path: S3 Bucket > Permissions > Object Ownership

Adopting these solutions resolves the ACL conflict while aligning with AWS security standards. Migrate to bucket policies for sustainable configurations.