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.