How to set granular S3 permissions per prefix
AWS IAM is the right tool for fine-grained per-prefix access — write a policy with two statements: s3:GetObject on the prefix wildcard, and s3:ListBucket on the bucket itself with a Condition on s3:prefix. The s3:prefix condition on listing is the part most people miss, which is why first-attempt policies let users read but not list. For human collaboration, S3 Viewer offers a simpler alternative: per-bucket roles assigned by email invite — Owner, Admin, Editor, or Viewer — without writing IAM at all.
Step-by-step.
- 01
Decide the scope
Bucket, prefix, or single key. The smaller the scope, the safer. - 02
IAM: write the read statement
Allows3:GetObjecton every key inside the prefix.Resourceuses a wildcard."Resource": "arn:aws:s3:::my-bucket/reports/finance/*" - 03
IAM: add the listing condition (the part most people miss)
Listing requiress3:ListBucketon the bucket itself (not the prefix), with aConditionons3:prefix. This is why most first-attempt IAM policies let users read but not list.{ "Version": "2012-10-17", "Statement": [ { "Sid": "ReadInsidePrefix", "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::my-bucket/reports/finance/*" }, { "Sid": "ListInsidePrefix", "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": "arn:aws:s3:::my-bucket", "Condition": { "StringLike": { "s3:prefix": ["reports/finance/*"] } } } ] } - 04
IAM: attach to a user or role and test
Attach the policy to the IAM user or role and verify with the IAM policy simulator before handing it over. Confirm both list and get work inside the prefix and deny outside. - 05
Team workflows: S3 Viewer per-bucket roles
Authoring an IAM policy per teammate is heavy for human collaboration. For team access, connect the bucket once with a least-privilege workspace credential and assign per-bucket roles: Viewer (read), Editor (read + write), Admin (manage members), Owner (full control). The workspace enforces access server-side; for finer per-prefix scoping within a bucket, layer in IAM as above. - 06
Verify
Try to list and read outside the prefix. Both should deny. If they don't, the policy is too broad — most likely theResourcewildcard is wrong or the listingConditionis missing.
What's actually happening.
S3 has no folders — “prefix-scoped” access is enforced by IAM policy on the key pattern. The catch is that listing requires a separate s3:ListBucket permission on the bucket ARN scoped via Condition/s3:prefix, which trips up most people writing their first IAM policy. For team collaboration, S3 Viewer offers an alternative: connect the bucket once with a workspace-level key and assign per-bucket roles to invited members. The workspace enforces those roles server-side, so you don't have to write a new IAM policy every time you onboard someone.
Common questions.
How do I give someone access to one folder in an S3 bucket?
Why does my IAM policy let users read S3 files but not list the folder?
What's the difference between s3:ListBucket and s3:GetObject?
Can I scope down to a single S3 key?
Do I need a custom IAM policy for every teammate?
Does this work with Cloudflare R2?
Skip the CLI. Try it in the browser.
S3 Viewer turns the steps above into a single click. Open source, self-hostable, free for personal use.
Why teams pick this
More how-tos
Invite a teammate
Skip per-person IAM users for human collaboration. Email invite, per-bucket role, one-click revoke.
Share an S3 file
Presigned URL or workspace invite — when each is the right call, and why presigned links can't be revoked.
Delete a file
Versioning, delete markers, MFA Delete — and how to actually purge instead of soft-deleting.