How to Migrate Legacy S3 Buckets Off ACLs to Bucket Owner Enforced
Retrospective: this article looks back at events from April 2023, written in 2026 with the benefit of hindsight.
New S3 buckets have ACLs disabled by default, but older buckets may still rely on them. Migrating to "Bucket owner enforced" simplifies access control. Here is how.
Step 1: Find buckets with ACLs enabled
Use the S3 console (Object Ownership column), AWS Config, or Security Hub control S3.12 ("ACLs should not be used to manage user access to buckets"). Also check S3 Storage Lens and S3 Inventory for object ACL usage.
Step 2: Understand how ACLs are used
For each bucket:
- Review the bucket ACL (grants beyond the owner?).
- Check whether objects have ACLs granting access to other accounts or groups.
- Check whether applications upload objects with ACLs (for example,
bucket-owner-full-controlfrom another account).
Enable S3 server access logs or CloudTrail data events and look for requests that rely on ACL permissions.
Step 3: Replace ACL grants with policies
- Cross-account access: grant via bucket policy (and KMS key policy if using SSE-KMS).
- Public access (if intended): serve through CloudFront with Origin Access Control instead.
- Log delivery: use bucket policies for services like ELB and CloudFront logging (most now support policy-based delivery).
Step 4: Switch Object Ownership
Set Object Ownership to Bucket owner enforced. ACLs are disabled, and the bucket owner owns all objects.
If an application still sends ACLs other than bucket-owner-full-control, requests will fail — test first.
Step 5: Prevent regression
Use an SCP or Config rule to detect or prevent changing Object Ownership back.
Verify
Security Hub S3.12 passes for all buckets.
- S3 Block Public Access and ACLs Disabled by Default for New Buckets (Apr 2023) Platform Changes
- S3 Object Ownership and ACL Cleanup Checklist How-To & Hardening
- CIO Brief: Secure Defaults Help — But Only for New Resources CIO Briefings