How S3 decides access: policies, ownership, Block Public Access, access points

The S3-specific layers on top of IAM evaluation — default behaviour with no bucket policy, Object Ownership and ACLs, Block Public Access and S3's exact definition of a "public" policy, access points — and the permissions needed to manage each.

markdownreferencev4J2GR-47WCstage: referencetrust: officialservice: s3interface: anybucket policyObject OwnershipBucketOwnerEnforcedACLs disabledbucket-owner-full-controlBlock Public AccessBlockPublicAclsIgnorePublicAclsBlockPublicPolicyRestrictPublicBucketspublic policyaccess points3:ListBucket

Created 18 Oct 2026 · Modified 23 Oct 2026 · 4 versions

How S3 decides access

S3 runs normal IAM policy evaluation (reference/iam/policy-evaluation.md), and adds three S3-only controls that can refuse a request IAM would allow: Object Ownership (who owns an object, and whether ACLs exist at all), Block Public Access (which overrides "public" grants), and access point configuration. New buckets are private: ACLs disabled, all four Block Public Access settings on, SSE-S3 encryption.

Default behaviour

  • No bucket policy: identities in the bucket owner's account can use the bucket if their own IAM policies allow it; other accounts and anonymous requests are denied.
  • Same account: an Allow in either the IAM policy or the bucket policy is enough.
  • Cross-account: both the caller's IAM policy and the bucket policy must allow.
  • Bucket vs object ARNs: bucket actions (s3:ListBucket) use arn:aws:s3:::<bucket>; object actions (s3:GetObject, s3:PutObject) use arn:aws:s3:::<bucket>/*. A statement with only one form silently misses the other.
  • s3:ListBucket also changes errors: without it, a request for a missing object returns 403 instead of 404.

Object Ownership and ACLs

SettingOwner of new objectsACLs
Bucket owner enforced (default for new buckets; recommended)Always the bucket ownerDisabled; they no longer affect access. A PUT carrying any ACL other than bucket-owner-full-control fails with AccessControlListNotSupported (400).
Bucket owner preferredBucket owner if the upload carries bucket-owner-full-control, otherwise the writerEnabled
Object writerThe uploading accountEnabled

Why it matters: a bucket-policy Allow applies only to objects the bucket owner owns; a bucket-policy Deny applies to all objects. In a bucket with ACLs enabled, an object uploaded by another account can be granted only by its ACL, so the bucket owner may get 403 on its own bucket.

Moving to Bucket owner enforced: first migrate any ACL grants to bucket-policy statements, find requests that depend on ACLs, and update policies that use ACL condition keys. Afterwards the bucket owner owns everything; reads of ACLs still work and show only the owner. Permissions: s3:PutBucketOwnershipControls and s3:GetBucketOwnershipControls.

aws s3api get-bucket-ownership-controls --bucket <bucket>

Block Public Access

Four independent settings, at the access point, bucket and account levels; at the organization level all four are applied together as one policy and override account settings. S3 enforces the most restrictive combination of the levels that apply. Account settings apply in every Region (propagation can take time). There is no per-object setting.

SettingEffectDenial reads
BlockPublicAclsRejects PutBucketAcl/PutObjectAcl with a public ACL, PutObject/CopyObject/POST with a public ACL, and (account level) CreateBucket with a public ACL. Existing ACLs untouched.because public ACLs are prevented by the BlockPublicAcls setting in S3 Block Public Access.
IgnorePublicAclsIgnores public ACLs on the bucket and its objects.implicit: because no resource-based policy allows …
BlockPublicPolicyRejects PutBucketPolicy (and access point policies) that would be public. Existing policies untouched. Apply it at the account level: at bucket level, someone who can edit the bucket policy could turn it off.because public policies are prevented by the BlockPublicPolicy setting in S3 Block Public Access.
RestrictPublicBucketsFor a bucket or access point whose policy is public, allows only AWS service principals and the owner's account; blocks all cross-account and anonymous access, including non-public statements in the same policy.explicit: with an explicit deny in a resource-based policy

Turning a setting off does not change policies or ACLs, so anything public under it becomes public again immediately. GetBucketAcl/GetObjectAcl report the effective permissions, not the stored ACL.

What S3 counts as "public"

  • ACL: grants anything to the AllUsers or AuthenticatedUsers groups.
  • Bucket policy: S3 starts by assuming public, and a statement is non-public only if it limits access with fixed values (no wildcards, no policy variables) of at least one of: a specific principal (or aws:PrincipalOrgID), aws:SourceIp with a narrow range, aws:SourceArn, aws:SourceVpc, aws:SourceVpce, aws:SourceOwner, aws:SourceAccount, aws:userid (outside the AROLEID:* pattern), s3:DataAccessPointArn, s3:DataAccessPointAccount.
  • aws:SourceIp ranges broader than /8 (IPv4) or /32 (IPv6), excluding RFC 1918 private ranges, count as public.
  • "aws:SourceVpc": "vpc-*" is public; "aws:SourceVpc": "vpc-<id>" is not.
  • One public statement makes the whole policy public, which brings RestrictPublicBuckets into force for every statement in it.
  • A policy that allows an action S3 does not support can be judged public by Block Public Access even when IAM Access Analyzer disagrees; remove unsupported actions.

Permissions: s3:GetBucketPolicyStatus, s3:Get/PutBucketPublicAccessBlock, s3:Get/PutAccountPublicAccessBlock (DELETE uses the PUT permission).

Access points

Requests through an access point are also checked against its network origin (a VPC origin rejects anything not from that VPC), its own Block Public Access settings (fixed at creation), the access point policy, and, for cross-account access points, the bucket policy, which must authorize requests from the access point. An access point with a VPC origin is always non-public. Unlike bucket policies, an access point policy granting to s3:DataAccessPointArn wildcards is public.

If a policy locks everyone out

A bucket policy that denies everyone can be removed by the account root user. In an AWS Organizations member account, a privileged root session started from the management account can delete it.

Read this document as markdown — the same bytes an agent receives.