All IAM policy templates
AWS IAM policy template • S3

S3 Read-Only Access

Read and list objects in one bucket — no write, no delete, no bucket-config changes.

Policy

Replace the placeholder ARNs (YOUR-BUCKET-NAME, ACCOUNT_ID, REGION, etc.) with your real resource identifiers before use.

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

Why it's scoped this way

  • Two separate statements because s3:ListBucket is a bucket-level action (resource is the bucket ARN) and s3:GetObject is an object-level action (resource is bucket ARN + /*) — combining them under one Resource silently breaks one of the two.
  • No s3:PutObject, s3:DeleteObject, or s3:PutBucketPolicy — a compromised credential with this policy cannot modify or exfiltrate-and-delete the source data.
  • Scoped to one bucket ARN, not Resource: "*" — this policy has zero blast radius outside YOUR-BUCKET-NAME.

Hardening it further

  • Add a aws:SourceVpce condition if access should only come through a VPC endpoint.
  • If only a prefix is needed, scope Resource to arn:aws:s3:::YOUR-BUCKET-NAME/prefix/* instead of the whole bucket.

Paste your finished policy into the free AI-Powered IAM analyzer to catch anything you loosened while filling it in.

Related templates

Check your finished policy — free

Shieldly's AI-Powered analyzer flags privilege-escalation paths, wildcards, and risky PassRole in seconds. No signup, no AWS credentials. Also ships as CLI, VS Code extension, GitHub Action, and CDK Guard.

Amazon Web Services (AWS) is a trademark of Amazon.com, Inc. Shieldly is not affiliated with, endorsed by, or sponsored by Amazon Web Services.