S3 bucket policy uses wildcard actions and principals

Wildcard actions and principals in an S3 policy can grant more access than needed. Check the actual actions, resources, and conditions, then apply least privilege.

Description

Wildcards in Action and Principal can authorize unintended operations or principals. s3:* represents all S3 actions, while s3:Get* represents only a subset. Effective permissions also depend on Resource, conditions, explicit denies, and Block Public Access. A policy scoped only to object ARNs does not grant every bucket administration action.

Potential impact

  • Read permissions may expose object contents to principals that do not need access.
  • Write or delete permissions may allow unwanted uploads, changes to object contents, or data loss.
  • Excessive permissions can disrupt deployments and services using the storage. The impact depends on the actual actions and resources allowed.

Remediation

  • Specify the necessary actions, principals, and resource ARNs, and narrow unnecessary wildcards. Even when public reads are required, restrict write and administration permissions separately.
  • Check conditions, explicit denies, and account and bucket Block Public Access together. A private ACL does not cancel access granted by a bucket policy.
  • Apply the policy using resources supported by your provider and module versions. S3 module 3.7.0 requires attach_policy = true for a custom policy. Test that required access remains available and unapproved access is denied.

Legacy policy examples

These older inline examples illustrate the difference in action scope. AWS provider 4.2.0 documents policy and acl as read-only, requiring a separate policy resource with that version. Check current Object Ownership and Block Public Access requirements for new buckets too. Use an available unique bucket name and do not apply both alternatives together.

Allow all object actions

hcl
resource "aws_s3_bucket" "open_bucket" {
  bucket = "example-s3b-181355"
  acl    = "private"

  policy = <<EOF
  {
    "Id": "id113",
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": [
          "s3:*"
        ],
        "Effect": "Allow",
        "Resource": "arn:aws:s3:::example-s3b-181355/*",
        "Principal": "*"
      }
    ]
  }
  EOF
}

The policy allows wildcard principals to perform all S3 actions applicable to the object ARN scope. acl = "private" does not cancel that grant. This is distinct from granting every bucket administration action.

Narrow only the action to object writes

hcl
resource "aws_s3_bucket" "restricted_bucket" {
  bucket = "example-s3b-181355"
  acl    = "private"

  policy = <<EOF
  {
    "Id": "id113",
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": [
          "s3:putObject"
        ],
        "Effect": "Allow",
        "Resource": "arn:aws:s3:::example-s3b-181355/*",
        "Principal": "*"
      }
    ]
  }
  EOF
}

The action scope is narrower, but object writes are still granted to Principal: "*". AWS action names are case-insensitive, so s3:putObject is a write permission too. This does not resolve public writes; further restrict access to approved principals and the objects they need.

References